由于某种原因,我有两个类用模板实现运算符“+”, (我这样做是因为我希望这两个班级的所有孩子都能够使用它。)
我已经找到了一个非常简单的代码来实现我想要使用的东西:
#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的不同孩子。
答案 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