C++ gcc中的不明确重载,可以使用msvc
以下代码在msvc 18.00中编译良好,但在gcc 4.9.1中编译失败:C++ gcc中的不明确重载,可以使用msvc,c++,templates,C++,Templates,以下代码在msvc 18.00中编译良好,但在gcc 4.9.1中编译失败: #include <type_traits> template <int N> class Num { }; class Zero { }; template <int N, int M> Num<N + M> operator+(Num<N>, Num<M>) { return {}; } template <int N>
#include <type_traits>
template <int N> class Num { };
class Zero { };
template <int N, int M>
Num<N + M> operator+(Num<N>, Num<M>)
{
return {};
}
template <int N>
Zero operator+(Num<N>, Num<-N>)
{
return {};
}
int main()
{
Num<1> one;
Num<-1> mone;
Num<0> null;
auto a = one + one;
static_assert(std::is_same<decltype(a), Num<2>>::value, ":(");
auto b = one + mone;
static_assert(std::is_same<decltype(b), Zero>::value, ":(");
auto c = null + null;
static_assert(std::is_same<decltype(c), Zero>::value, ":(");
}
#包括
模板类Num{};
零类{};
模板
Num运算符+(Num,Num)
{
返回{};
}
模板
零运算符+(Num,Num)
{
返回{};
}
int main()
{
第一;
钱数;
numnull;
自动a=1+1;
静态断言(std::is_same::value,“:(”);
自动b=一个+货币;
静态断言(std::is_same::value,“:(”);
自动c=null+null;
静态断言(std::is_same::value,“:(”);
}
gcc的错误消息是:
ambiguous.cpp: In function 'int main()':
ambiguous.cpp:28:16: error: ambiguous overload for 'operator+' (operand types are 'Num<1>' and 'Num<-1>')
auto b = one + mone;
^
ambiguous.cpp:28:16: note: candidates are:
ambiguous.cpp:8:12: note: Num<(N + M)> operator+(Num<N>, Num<M>) [with int N = 1; int M = -1]
Num<N + M> operator+(Num<N>, Num<M>)
^
ambiguous.cpp:14:6: note: Zero operator+(Num<N>, Num<(- N)>) [with int N = 1]
Zero operator+(Num<N>, Num<-N>)
^
ambiguous.cpp:29:47: error: template argument 1 is invalid
static_assert(std::is_same<decltype(b), Zero>::value, ":(");
^
ambiguous.cpp:31:17: error: ambiguous overload for 'operator+' (operand types are 'Num<0>' and 'Num<0>')
auto c = null + null;
^
ambiguous.cpp:31:17: note: candidates are:
ambiguous.cpp:8:12: note: Num<(N + M)> operator+(Num<N>, Num<M>) [with int N = 0; int M = 0]
Num<N + M> operator+(Num<N>, Num<M>)
^
ambiguous.cpp:14:6: note: Zero operator+(Num<N>, Num<(- N)>) [with int N = 0]
Zero operator+(Num<N>, Num<-N>)
^
ambiguous.cpp:32:47: error: template argument 1 is invalid
static_assert(std::is_same<decltype(c), Zero>::value, ":(");
^
undigulary.cpp:在函数“int main()”中:
不明确。cpp:28:16:错误:“运算符+”的重载不明确(操作数类型为“Num”和“Num”)
自动b=一个+货币;
^
不明确。cpp:28:16:注:候选人为:
不明确的.cpp:8:12:注意:Num运算符+(Num,Num)[带int N=1;int M=-1]
Num运算符+(Num,Num)
^
不明确的.cpp:14:6:注意:零运算符+(Num,Num)[带int N=1]
零运算符+(Num,Num)
^
不明确。cpp:29:47:错误:模板参数1无效
静态断言(std::is_same::value,“:(”);
^
不明确。cpp:31:17:错误:“运算符+”的重载不明确(操作数类型为“Num”和“Num”)
自动c=null+null;
^
不明确。cpp:31:17:注:候选人为:
不明确的.cpp:8:12:注意:Num运算符+(Num,Num)[带int N=0;int M=0]
Num运算符+(Num,Num)
^
不明确的.cpp:14:6:注意:零运算符+(Num,Num)[带int N=0]
零运算符+(Num,Num)
^
不明确。cpp:32:47:错误:模板参数1无效
静态断言(std::is_same::value,“:(”);
^
哪个编译器是对的?我不想这么说,但MSVC是对的,也有错!为了简化,我们调用:
operator+(Num<1>, Num<-1>)
运算符+(Num,Num)
对于重载:
operator+(Num<N>, Num<M>)
operator+(Num<N>, Num<-N>)
运算符+(Num,Num)
运算符+(Num,Num)
两人显然都是可行的候选人。而且,根据[over.match.best]:
根据这些定义,一个可行函数F1
被定义为比另一个可行函数更好的函数
F2
如果对于所有参数i
,ICSi(F1
)的转换顺序不比ICSi(F2
)差,则
- [……]
和F1
是函数模板的专门化,而F2
的函数模板更为专门化 根据14.5.6.2中所述的偏序规则,比F2的模板F1
操作符+(Num,Num)
,不能用它调用操作符+(Num,Num)
。但是,第二个重载变成操作符+(Num,Num)
,使用它可以调用第一个重载
因此,重载执行
Num
比重载执行Num
更加专业化,因此应该明确地首选它。不是答案,但您可以通过消除第二个重载并使用Zero=Num将Zero
更改为,从而消除这种歧义;
@TartanLlama这只是一个玩具代码举例说明问题。