我正在将大量地理空间代码从一个投影转换为另一个投影。为了在此转换期间强制执行适当的单位,我引入了距离,点,矩形和多边形模板,这些模板采用标记来指示使用的坐标系。这样做效果很好,但是有很多地方会对非零(!= 0
)或正值(> 0
)执行检查。我希望能够重载这些运算符,以便在不与任何其他数字进行比较的情况下与0
进行比较。是否有可能实现这一目标?
作为一项额外的限制,我无法使用constexpr
,因为我必须支持VS 2013,但我仍然有兴趣了解是否有办法使用constexpr
仅供参考,我正在使用类似的东西:
template<typename Tag> struct Distance
{
int value;
};
template<typename Tag> struct Point
{
Distance<Tag> x;
Distance<Tag> y;
};
// This works fine for comparing two Distances
template<typename Tag> bool operator>(const Distance<Tag>& a, const Distance<Tag>& b) {return a.value > b.value;}
// But I don't want this to allow a > 14, only a > 0
template<typename Tag> bool operator>(const Distance<Tag>& a, int b) {return a.value > b;}
struct Mercator;
typedef Point<Mercator> MercPoint;
struct GuiScale;
typedef Point<GuiScale> GuiPoint;
// etc.
答案 0 :(得分:2)
您可以将nullptr_t
用作黑客(将文字0
转换为nullptr
):
template<typename Tag> bool operator>(const Distance<Tag>& a, std::nullptr_t b) {return a.value > 0;}
答案 1 :(得分:2)
您可以使用字面零的转换为任意指针:
#include <type_traits>
template<typename Tag>
struct Distance
{
private:
using literal_zero = void(Distance::*)();
template<typename U>
using enable_nullptr = typename std::enable_if<
std::is_same< typename std::decay< U >::type, std::nullptr_t >::value
>::type;
public:
int value;
bool operator<( literal_zero ) const { return value < 0; }
template<typename U>
enable_nullptr<U> operator<( const U& ) const = delete;
};
int main() {
Distance<int> a;
a.value = 0;
a < 0;
// a < 42; // does not compile
// a < nullptr; // does not compile
}
与其他答案不同,这也不允许a < nullptr
。此外,如果删除nullptr
相关部分并将using literal_zero = ...
替换为typedef
,则相同的技巧也适用于C ++ 98。
答案 2 :(得分:1)
如果它在语义上与文字0
进行比较有效,那么它也有效,允许从文字0
进行转换。转换到位后,您无需进行特殊情况比较(Live at Coliru):
template<typename Tag> struct Distance
{
int value;
Distance() = default;
explicit constexpr Distance(int v) : value(v) {}
constexpr Distance(std::nullptr_t) : value(0) {}
friend constexpr bool operator == (const Distance& lhs, const Distance& rhs) {
return lhs.value == rhs.value;
}
friend constexpr bool operator < (const Distance& lhs, const Distance& rhs) {
return lhs.value < rhs.value;
}
// ...
};