C++ 特定积分常数的重载比较
我正在将一大组地理空间代码从一个投影转换为另一个投影。为了在转换过程中强制使用适当的单位,我引入了距离、点、矩形和多边形模板,这些模板使用一个标记来指示使用的坐标系。这是一个很好的解决方案,但是在很多地方,对非零(C++ 特定积分常数的重载比较,c++,templates,c++11,C++,Templates,C++11,我正在将一大组地理空间代码从一个投影转换为另一个投影。为了在转换过程中强制使用适当的单位,我引入了距离、点、矩形和多边形模板,这些模板使用一个标记来指示使用的坐标系。这是一个很好的解决方案,但是在很多地方,对非零(!=0)或正值(>0)执行检查。我希望能够重载这些运算符,以允许与0进行比较,而不与任何其他数字进行比较。有可能做到这一点吗 作为一个额外的限制,我不能使用constexpr,因为我必须支持VS 2013,但我仍然想知道是否有办法使用constexpr 仅供参考,我正在处理以下内容:
!=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.
模板结构距离
{
int值;
};
模板结构点
{
距离x;
距离y;
};
//这适用于比较两个距离
模板布尔运算符>(常量距离&a,常量距离&b){返回a.value>b.value;}
//但我不希望这允许a>14,只允许a>0
模板布尔运算符>(常量距离&a,int b){返回a.value>b;}
结构墨卡托;
typedef Point MercePoint;
结构尺度;
typedef点GuiPoint;
//等等。
您可以使用nullptr\t
作为一种攻击(作为literal0
转换为nullptr
):
模板布尔运算符>(常量距离&a,std::nullptr_t b){返回a.value>0;}
您可以使用nullptr\t
作为一种攻击(作为literal0
转换为nullptr
):
模板布尔运算符>(常量距离&a,std::nullptr_t b){返回a.value>0;}
您可以使用到文字零的任何指针的转换:
#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
}
#包括
样板
结构距离
{
私人:
使用literal_zero=void(距离::*)();
样板
使用enable_nullptr=typename std::enable_if<
std::is_same:type,std::nullptr_t>:value
>::类型;
公众:
int值;
bool运算符您可以使用到文本零的任何指针的转换:
#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
}
#包括
样板
结构距离
{
私人:
使用literal_zero=void(距离::*)();
样板
使用enable_nullptr=typename std::enable_if<
std::is_same:type,std::nullptr_t>:value
>::类型;
公众:
int值;
bool运算符如果与literal0
进行比较在语义上是有效的,则允许从literal0
进行转换也是有效的。转换到位后,不需要特殊情况比较():
模板结构距离
{
int值;
距离()=默认值;
显式constexpr距离(int v):值(v){}
constexpr距离(std::nullptr_t):值(0){
friend constexpr bool运算符==(常量距离和左侧、常量距离和右侧){
返回lhs.value==rhs.value;
}
friend constexpr布尔运算符<(const Distance&lhs、const Distance&rhs){
返回lhs.value
如果与文字0
进行比较在语义上是有效的,那么允许从文字0
进行转换也是有效的。转换到位后,不需要特殊情况比较():
模板结构距离
{
int值;
距离()=默认值;
显式constexpr距离(int v):值(v){}
constexpr距离(std::nullptr_t):值(0){
friend constexpr bool运算符==(常量距离和左侧、常量距离和右侧){
返回lhs.value==rhs.value;
}
friend constexpr布尔运算符<(const Distance&lhs、const Distance&rhs){
返回lhs.value
为什么不使用布尔函数,如IsZero
?在我看来,重载只取1个允许值的数学运算符是个坏主意。距离类模板的意义是什么?@P0W,因此不能给运算符>
(或另一个函数)提供两个不相关的距离并给整数类型一个与其用途相对应的名称。签出这些:这些类型是中间转换步骤的一部分,还是应该保留为最终形式?如果代码要保留这些类型,我将重构为命名函数(.isZero()
,isPositive()
)…但如果类型只是暂时的,那么这可能需要更多的工作为什么不使用bool函数,例如IsZero
?在我看来,重载只取1个允许值的数学运算符是个坏主意。距离
类模板@P0W有什么意义,所以你不能给运算符>
(或另一个函数)并为整数类型指定与其用途相对应的名称。签出这些:这些类型是中间转换步骤的一部分,还是应该保留为最终形式?如果代码要保留这些类型,我将重构为命名函数(.isZero()
,isPositive()
)…但是如果类型只是暂时的,这可能是更多的工作。我没有想到这种转换。这看起来像是要走的路。谢谢!我没有想到这种转换。这看起来像是要走的路。谢谢!我只是想说清楚。我只是想说清楚。
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;
}
// ...
};