C++ 如何对包含类型的变量使用比较运算符?
我在代码中使用了很多变量,我需要在某些地方与内容进行比较,以测试变量的内容的值 例如:C++ 如何对包含类型的变量使用比较运算符?,c++,boost-variant,C++,Boost Variant,我在代码中使用了很多变量,我需要在某些地方与内容进行比较,以测试变量的内容的值 例如: if(equals<int>(aVariant, 0)){ //Something } else { //Something else } 但我无法提供该操作符的有效实现。问题是==运算符已经在变量中实现,以在编译时失败 有人知道实现它的方法吗?还是一种禁用此限制的方法?即使我必须为变量中包含的每个可能类型实现一个版本,这也不是问题 感谢如评论所述,我认为解决这一难题的最干净的方
if(equals<int>(aVariant, 0)){
//Something
} else {
//Something else
}
但我无法提供该操作符的有效实现。问题是==运算符已经在变量中实现,以在编译时失败
有人知道实现它的方法吗?还是一种禁用此限制的方法?即使我必须为变量中包含的每个可能类型实现一个版本,这也不是问题
感谢如评论所述,我认为解决这一难题的最干净的方法是使用允许客户端覆盖外部使用行为的运营商策略(每个运营商)增强
boost::variant
的实现。(显然,这是大量的通用编程工作)
我已实施了一个变通办法。这允许您为变体实现自定义运算符,即使它在boost/variant.hpp
中实现了这些运算符
我的脑波是使用
我们的想法是通过使我们的变体具有不同的实际类型来打破重载解析(或者至少使我们的自定义重载成为首选解析)(这让人想起了一个“绝望的”ADL障碍:你不能从作用域中使用可见的名名名,也不能转到“非军事化的命名空间”(障碍)因为冲突声明位于类名称空间本身;但是您可以使它们不适用于您的“诱饵”类型)
唉,这对于操作符
> */ \ { \ T\ 显式D(constt):T(T){}\ D(){}\ D(常数D&t):t(t.t){\ D&operator=(const D&rhs){t=rhs.t;返回*this;}\ D&运算符=(常量T&rhs){T=rhs;返回*this;}\ 运算符常量T&()常量{return T;}\ 运算符T&({return T;}\ /*布尔运算符==(常量D&rhs)常量{return t==rhs.t;}*/\
/*布尔operator@R.MartinhoFernandes我不认为他会用这个语法。哦,我不知道这个场景被变体开发者明确禁止。有人知道原因是什么吗?@R.MartinhoFernandes:没人想到?他们可以使用或comparisontraits
@Baptiste,您可以修改variant类来实现这一点,并将想法提交到boost列表中。手册中说:“重载返回void的存在只是为了禁止将操作符的右侧隐式转换为variant;因此,它的使用(有意地)将导致编译时错误。”-如果(aVariant==variant\u type(0))可以执行policies
,但我看不出用户定义函数会有什么问题(通常可以推断参数类型).@UncleBens我的用户定义函数没有问题,只是语法在我的代码中有点重。它工作得很好:)我只需要添加一些函数,以与自定义类型上的variant相同的方式工作。非常感谢。template<typename V, typename T> inline bool equals(V& variant, T value){ return boost::get<T>(&variant) && boost::get<T>(variant) == value; }
if(aVariant == 0){ //Something } else { //Something else }
#include <boost/variant.hpp> #include <boost/lexical_cast.hpp> #include <string> #include <iostream> ///////////////////////////////////////////////////// // copied and reduced from boost/strong_typedef.hpp #define CUSTOM_STRONG_TYPEDEF(T, D) \ struct D \ /*: boost::totally_ordered1< D */ \ /*, boost::totally_ordered2< D, T */ \ /*> > */ \ { \ T t; \ explicit D(const T t_) : t(t_) {}; \ D(){}; \ D(const D & t_) : t(t_.t){} \ D & operator=(const D & rhs) { t = rhs.t; return *this;} \ D & operator=(const T & rhs) { t = rhs; return *this;} \ operator const T & () const {return t; } \ operator T & () { return t; } \ /*bool operator==(const D & rhs) const { return t == rhs.t; } */\ /*bool operator<(const D & rhs) const { return t < rhs.t; } */\ }; namespace detail { typedef boost::variant<unsigned int, std::string> variant_t; struct less_visitor : boost::static_visitor<bool> { bool operator()(const std::string& a, int b) const { return boost::lexical_cast<int>(a) < b; } bool operator()(int a, const std::string& b) const { return a < boost::lexical_cast<int>(b); } template <typename T> bool operator()(const T& a, const T& b) const { return a < b; } }; struct variant_less { less_visitor _helper; bool operator()(const variant_t& a, const variant_t& b) const { return boost::apply_visitor(_helper, a, b); } }; } CUSTOM_STRONG_TYPEDEF(detail::variant_t, custom_vt); namespace { bool operator<(const custom_vt& a, const custom_vt& b) { return detail::variant_less()(a, b); } std::ostream& operator<<(std::ostream& os, const custom_vt& v) { return os << (const detail::variant_t&)v; } } int main() { const detail::variant_t I(43), S("42"); const custom_vt i(I), s(S); // regression test (compare to boost behaviour) std::cout << "boost: " << I << " < " << S << ": " << std::boolalpha << (I<S) << "\n"; std::cout << "boost: " << S << " < " << I << ": " << std::boolalpha << (S<I) << "\n"; // FIX1: clumsy syntax (works for boost native variants) detail::variant_less pred; std::cout << "clumsy: " << i << " < " << s << ": " << std::boolalpha << pred(i,s) << "\n"; std::cout << "clumsy: " << s << " < " << i << ": " << std::boolalpha << pred(s,i) << "\n"; std::cout << "clumsy: " << I << " < " << S << ": " << std::boolalpha << pred(I,S) << "\n"; std::cout << "clumsy: " << S << " < " << I << ": " << std::boolalpha << pred(S,I) << "\n"; // FIX2: neat syntax (requires a custom type wrapper) std::cout << "custom: " << i << " < " << s << ": " << std::boolalpha << (i<s) << "\n"; std::cout << "custom: " << s << " < " << i << ": " << std::boolalpha << (s<i) << "\n"; }
boost: 43 < 42: true boost: 42 < 43: false clumsy: 43 < 42: false clumsy: 42 < 43: true clumsy: 43 < 42: false clumsy: 42 < 43: true custom: 43 < 42: false custom: 42 < 43: true