c – 如何模拟一组相关类的运算符重载而不与标准库运算符冲突?
这似乎是一个相当直接的想法:我有一组类,我应该能够编写一个运算符,让我们说减法,基本上使用完全相同的代码.
试图以“明显”的方式做到这一点时,即: template <typename T> T operator-(T a,const T& b) { return a -= b; } 然后,在某些编译器上,这似乎与迭代器的减法运算符冲突(特别是它在gcc 3.4.6和Apple LLVM上打破,虽然看起来在gcc版本4或更新版本上正常工作),但是我收到以下错误: error: use of overloaded operator '-' is ambiguous (with operand types 'std::__1::__wrap_iter<const double *>' and 'const_iterator' (aka '__wrap_iter<const_pointer>')) 我还考虑了模板重载只是一个基类,从中可以派生出组中的所有类,但是由于第一个参数是按值传递的,我认为特定于子类的信息在复制期间会丢失. 我错过了一些明显的东西吗有没有办法让所有这些编译器都满意? 编辑:理想情况下,解决方案应该在C 03中工作. 解决方法
使用基类,adl koenig运算符和sfinae.
namespace ops{ struct subtract_support{ template<class T,std::enable_if_t<std::is_base_of<subtract_support,T>{},int> =0 > friend T operator-( T lhs,T const& rhs ){ lhs-=rhs; return lhs; } }; } 现在继承自ops :: subtract_support会导致 – 适用于您的类型. (注意两行主体:确保lhs移出 –,与OP中的版本不同). 仅仅命名空间限制会导致您找到任何模板生成类型,其中一个tge参数来自您的命名空间,以及其他非预期的情况:adl对模板成员来自特定命名空间的类型进行操作. 这个技巧允许您在声明时将每种类型标记为使用此技术. 这种技术几乎没有二元布局含义.但是如果你需要一些模糊的东西,比如前缀的布局兼容性,则可能需要特征类. 现在,这是一个C 11解决方案.显然OP需要C 03.好吧,最好的方法是像C 11一样实现它,这样在升级编译器时可以删除代码. enable_if可以很容易地用C 03编写.is_base_of需要多几行: namespace notstd{ namespace details{ template<class T,class U> struct base_test{ typedef char no; // sizeof(1) struct yes { no unused[2]; }; // sizeof(2) or greater static yes test(T*); // overload if arg is convertible-to-T* static no test(...); // only picked if first overload fails // pass a `U*` to `test`. If the result is `yes`,T // is a base of U. Note that inaccessible bases might fail here(?) // but we are notstd,good enough. enum {value= ( sizeof(yes)==sizeof(test((U*)0)) )}; }; } template<class Base,class T> struct is_base_of{ enum{value=details::base_test<Base,T>::value}; }; template<bool b,class T=void> struct enable_if {}; template<class T> struct enable_if<true,T> { typedef T type; }; } 我们还需要在模板ADL运算符中调整SFINAE以符合C 03: namespace ops{ struct subtract_support{ template<class T> friend typename notstd::enable_if<notstd::is_base_of<subtract_support,T>::value,T>::type operator-( T lhs,T const& rhs ){ lhs-=rhs; return lhs; } }; } Live example. 1例如,如果Foo是具有贪婪 – 模板运算符的命名空间中的类型,则decltype(v0-v1)其中v0和v1是vector< Foo>将是矢量< Foo>.这是误报(它不会编译).但是vec3< Foo> (具有自己的3 Foo的向量空间)将导致相同的模糊性. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |