Ton*_*ony 3 c++ inheritance templates operator-overloading c++11
由于某种原因,我有两个类使用模板实现运算符"+"(我这样做是因为我希望这两个类的所有子节点都能够使用它).
我已经找到了一个非常简单的代码来实现我想要使用的东西:
#include <type_traits>
class A{};
template<typename T>
A operator+(T& lhs,int rhs){
  static_assert(std::is_base_of<A, T>::value, "T must inherit from A");
  A to_return;
  return to_return;
}
class B{};
template<typename T>
B operator+(T& lhs,int rhs){
  static_assert(std::is_base_of<B, T>::value, "T must inherit from B");
  B to_return;
  return to_return;
}
int main()
{
  A u;
  A v = u+1;
}
编译时,编译器(g ++或intel)返回以下错误:
g ++:main.cpp:25:11:错误:'u + 1'main.cpp中的'operator +'的模糊重载:25:11:注意:候选者是:main.cpp:6:3:注意:运算符+( T&,int)[with T = A] main.cpp:15:3:注意:B运算符+(T&,int)[T = A]
icpc:main.cpp(25):错误:多个运算符"+"匹配这些操作数:函数模板"运算符+(T&,int)"函数模板"B运算符+(T&,int)"操作数类型是: A + int A v = u + 1; ^
虽然它不是那么模糊,因为v应该是A类型,所以只有第一个模板才能工作.
任何想法绕过这个保持两个模板运营商?
或者另一个想法是让一个操作员为A和B的所有孩子工作?即对于A的所有C类孩子,我希望能够A w = u + 1; //where u is of type C.
为B 编写 
 和相同.
谢谢,
托尼
根据Barry给出的答案,std :: enable_if完成了这项工作.然而,事实证明我需要的是使用两个类型名称,Barry提出的技术必须稍加修改以增加这种可能性:
#include <type_traits>
#include <iostream>
class A{};
template<typename T1,typename T2 = typename std::enable_if<std::is_base_of<A,T1>::value, A>::type>
A operator+(T1& lhs,T2& rhs){
  A to_return;
  return to_return;
}
class B{};
template<typename T1,typename T2 = typename std::enable_if<std::is_base_of<B,T1>::value, B>::type>
B operator+(T2& lhs,T2& rhs){
  B to_return;
  return to_return;
}
int main()
{
  A u;
  A w = u+u;
}
然后它工作正常,即使T1和T2是A的不同孩子.
重载决策仅基于函数签名,即其名称,cv资格及其参数类型.
对于你的第一个,那就是:
operator+(T& lhs, int rhs);
而对于你的第二个,那也是:
operator+(T& lhs, int rhs);
由于它们是相同的,编译器无法区分这两者 - 因此模糊不清.解决此问题的一种方法是将静态断言移动到返回类型并使用SFINAE:
template<typename T>
typename std::enable_if<
    std::is_base_of<A, T>::value,
    A
>::type
operator+(T& lhs,int rhs){
    // stuff
}
对于您的其他运营商而言也是如此.这将一直有效,直到你尝试T从两者派生的一些,然后它将再次变得模棱两可.
或者,根据您实际使用的内容lhs,只需:
A operator+(A& lhs, int rhs); // already accepts anything that derives from A