C++模板,模棱两可的重载
C++ template, ambiguous overload
出于某种原因,我有两个类使用模板实现运算符"+",(我这样做是因为我希望这两个类的所有孩子都能使用它)。
我已经归结为一个非常简单的代码,实现我想使用的内容:
#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++ 或英特尔)返回以下错误:
G++:main.cpp:25:11:错误:"u + 1"中"运算符+"的不明确重载 主.cpp:25:11: 注意:候选人是: main.cpp:6:3: 注意:A 运算符+(T&, int) [T = A] main.cpp:15:3: 注意:B 运算符+(T&, int) [T = A]
ICPC : 主.cpp(25): 错误: 多个运算符 "+" 匹配以下操作数: 函数模板"运算符+(T &, int)" 函数模板"B 运算符+(T &, int)" 操作数类型为:A + 整数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 的不同子级。
重载解析完全基于函数签名,即其名称、简历限定和参数类型。
对于您的第一个,即:
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
- 模棱两可的重载模板
- 调用重载的"<大括号括起来的初始值设定项列表>"对于对来说就足够了是模棱两可的
- VSCode 说 std::chrono 是模棱两可的,如果运算符<<重载
- 修复重载运算符的使用'+'模棱两可?
- 涉及自定义类的奇怪的模棱两可的重载
- 给定一个已经定义的模板函数,是否可以用另一个模板函数重载它而不会模棱两可
- 模棱两可:优先考虑重载 f(A&) 而不是 f(A)
- 看似模棱两可的模板函数重载
- 重载函数的调用 - 以继承的类作为参数 - 是模棱两可的
- C++ libconfig 模棱两可的重载
- ISO C++ 表示这些是模棱两可的运算符重载
- 为什么下面的运算符重载是模棱两可的
- 模棱两可的重载函数 - 如何以及为什么
- C++模板,模棱两可的重载
- 为什么这些重载不模棱两可?
- c++中模棱两可的函数重载
- 对重载函数的模棱两可的调用,即使一个更专业
- 重载函数会产生模棱两可的错误
- Gtkmm,重载的'Scale()'的调用是模棱两可的
- 调用重载<大括号括起来的初始值设定项列表>是模棱两可的,如何处理?