【发布时间】:2015-01-12 05:14:36
【问题描述】:
出于某种原因,我有两个类使用模板实现运算符“+”, (我这样做是因为我希望这两个班级的所有孩子都能使用它)。
我已经得出了一个非常简单的代码来实现我想要使用的东西:
#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: 注意:A operator+(T&, int) [with T = A] main.cpp:15:3: 注意:B operator+(T&, int) [with T = A]
icpc : main.cpp(25): 错误:多个运算符“+”匹配这些操作数: 函数模板“A operator+(T &, int)” 函数模板“B 运算符+(T &, int)” 操作数类型为:A + int A v = u+1; ^
虽然它不像 v 应该是 A 类型那样模棱两可,但只有第一个模板应该工作。
有什么想法可以解决这个问题吗?保留两个模板运算符?
或者让操作员为 A 和 B 的所有孩子工作的另一个想法?
IE。对于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 的不同孩子。
【问题讨论】:
-
只是不要构建模板操作员采取任何措施(我认为这是一个设计缺陷) - 更具体
-
*"虽然它不像 v 应该是 A 类型那样模棱两可,但只有第一个模板应该工作。" * 你是从哪里得到这个想法的?
-
T 可以是第一个(分别是第二个)A(分别是 B)的任何孩子。如果有任何方法可以告诉编译器,我对这个解决方案很好。
-
您的 static_assert 不是可以从重载解决方案中排除重载的直接上下文,您是否尝试过SFINAE?
-
为什么不能模棱两可?解析中不考虑返回类型。
标签: c++ templates inheritance c++11 operator-overloading