c – 交换操作符的模板实现,合法吗?
发布时间:2020-12-16 07:24:36 所属栏目:百科 来源:网络整理
导读:我试图为我的一个类实现一个可交换的加法运算符: struct mytype{ constexpr mytype(othertype const ); constexpr mytype operator+(othertype const rhs) const;};templatetypename Tconstexpr auto operator+(T const lhs,mytype const rhs) - decltype(r
我试图为我的一个类实现一个可交换的加法运算符:
struct mytype { constexpr mytype(othertype const &); constexpr mytype operator+(othertype const &rhs) const; }; template<typename T> constexpr auto operator+(T const &lhs,mytype const &rhs) -> decltype(rhs + lhs) { return rhs + lhs; } 这个想法是,只要右手边是mytype,右手边接受的任何东西都可以在左手边接受. 这适用于icc和Visual Studio,并进入无限递归,解析gcc和clang上的decltype(当达到最大模板深度时终止). 我可以看到无限递归实际上可能更正确,如bug report所述:在进行重载解析之前需要专门化(因为它是重载决策的输入). 另一方面,商业编制者以某种方式管理(无论是偶然还是故意,都可能存在争议). 这里的正确行为是什么? 是否可以避免指定运算符应该是可交换的类的完整列表? 可编辑的例子: struct othertype {}; struct mytype { constexpr mytype() : value(1) { } constexpr mytype(int v) : value(v) { } constexpr mytype(othertype const &o) : value(2) { } // 1 constexpr mytype operator+(mytype const &rhs) const { return mytype(value + rhs.value); } constexpr mytype operator+(othertype const &rhs) const // 2 { return mytype(value + 2); } int value; }; template<typename T> constexpr auto operator+(T const &lhs,mytype const &rhs) -> decltype(rhs + lhs) { return rhs + lhs; } void test() { constexpr mytype mine; constexpr othertype other; constexpr auto result = other + mine; static_assert(result.value == 3); } 当转换// 1被删除时,问题就消失了,这在我的用例中没有用.单独的加法运算符// 2不足以帮助解决decltype:重载解析应该已经选择了,但问题发生在重载解析之前. 在为T = othertype专门化模板之后发生无限递归:将othertype转换为mytype在两侧都给出了mytype的加法表达式,这也可以通过模板解析(即使存在非模板). 解决方法
您可以使用SFINAE限制模板以丢弃运算符< mytype>(mytype const& lhs,mytype const& rhs):
template<typename T,typename std::enable_if<!std::is_same<T,mytype>::value,int>::type = 0> constexpr auto operator+(T const &lhs,mytype const &rhs) -> decltype(rhs + lhs) { return rhs + lhs; } Demo (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |