C ++模板,模糊重载

时间:2014-11-14 18:12:16

标签: c++ templates inheritance c++11 operator-overloading

由于某种原因,我有两个类用模板实现运算符“+”, (我这样做是因为我希望这两个班级的所有孩子都能够使用它。)

我已经找到了一个非常简单的代码来实现我想要使用的东西:

#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'中'operator +'的模糊重载     main.cpp:25:11:注意:候选人是:     main.cpp:6:3:注意:运算符+(T&amp;,int)[含T = A]     main.cpp:15:3:注意:B运算符+(T&amp;,int)[有T = A]

  • icpc:main.cpp(25):错误:多个运算符“+”匹配这些操作数:      功能模板“A operator +(T&amp;,int)”      功能模板“B运算符+(T&amp;,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的不同孩子。

1 个答案:

答案 0 :(得分:8)

重载分辨率完全基于函数 signature ,它的名称,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