c – 模板二进制运算符重载决策
我在使用Apple LLVM编译器(XCode 4.5.2附带)时遇到了问题,同时正确运行GCC.更重要的是比关于编译器问题的辩论(我认为GCC是正确的),这引发了关于重载运算符时模板特化的解决顺序的问题[1].
考虑一个简单的矩阵类模板< class T> class matrix_t,具有定义乘法结果类型的特征(带标量,矩阵或向量).这将类似于以下代码: template <class T,class U,class Enable = void> struct matrix_multiplication_traits { //typedef typename boost::numeric::conversion_traits<T,U>::supertype type; typedef double type; }; template <class T,int N> struct vectorN { std::vector<T> vect; vectorN() : vect(N) { for(int i = 0; i < N; i++) vect[i] = i; } }; template <class T> class matrix_t { std::vector<T> vec; public: matrix_t<T> operator*(matrix_t<T> const& r) const { std::cout << "this_type operator*(this_type const& r) const" << std::endl; return r; } template <class U> matrix_t<typename matrix_multiplication_traits<T,U>::type> operator*(U const &u) const { std::cout << "different_type operator*(U const &u) const" << std::endl; return matrix_t<typename matrix_multiplication_traits<T,U>::type>(); } }; 还要考虑vectorN的运算符*的特化: template <class T,int N> //vectorN<typename matrix_multiplication_traits<T,U>::type,N> vectorN<double,N> operator*(matrix_t<T> const&m,vectorN<U,N> const&v) { std::cout << "vectorN operator*(matrix,vectorN)" << std::endl; //return vectorN<typename matrix_multiplication_traits<T,N>(); return vectorN<double,N>(); } 并考虑一个简单的测试程序: int main(int argc,const char * argv[]) { matrix_t<double> test; vectorN<double,10> my_vector; test * my_vector; // problematic line return 0; } “有问题的行”在GCC和模板<类U>上运行全局定义的运算符*(matrix_t< T> const&,vectorN< U,N> const&). LLVM上的matrix_t< T> :: operator *(U const&)const.因此,就像matrix_t< T> :: operator *(U const&)正在捕获所有模板特化查找.一个简单的“修复”是将全局运算符*移动到矩阵类中. 我首先认为这是特质课中的一个问题,可能过于复杂或错误(SFINAE).但即使简化特征或完全禁用它(如在粘贴代码中)也会产生错误.然后我认为这是一个订单问题(比如Herb Shutter的文章),但是在matrix_t声明和定义之间移动全局运算符*并没有改变. 这是个问题 当然,真正的问题是模板<类U> matrix_t :: operator *(U const&)const太笼统了,但是: >标准所涉及的这类问题是什么? [1]我已经阅读了关于模板专业化顺序的Herb Shutter建议. 解决方法
根据C 11标准第13.3.1 / 2段的规定:
此外,标准成员函数中没有提到优先于非成员函数,反之亦然.
是.选择全局运算符(应该是!)的原因是它是比类中定义的函数模板更专业的模板:在模板参数推导之后,N>常量和放大器;和matrix_t< T>常量和放大器;可以使matrix_t< T>匹配常量和放大器; r,但前者比后者更专业,因此,它是优选的. 根据第13.3.3 / 1段:
因此:
此行为符合错误.但请注意,这些不是专业化,而是重载. 最后:
我想你可以说它是一个(全局)运算符重载模板.它不是专门化,因为模板函数特化具有不同的语法.因此,没有专门的主要模板.它只是一个函数模板,一旦实例化,就会生成乘法运算符的重载. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |