Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ gcc中的不明确重载,可以使用msvc_C++_Templates - Fatal编程技术网

C++ gcc中的不明确重载,可以使用msvc

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>

以下代码在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>
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
    是函数模板的专门化,而
    F1
    的函数模板更为专门化 根据14.5.6.2中所述的偏序规则,比F2的模板
确定偏序的规则归结为:对于每个模板参数,合成一个新的类型/值,并尝试用它调用另一个重载。对于第一个重载,它变成
操作符+(Num,Num)
,不能用它调用
操作符+(Num,Num)
。但是,第二个重载变成
操作符+(Num,Num)
,使用它可以调用第一个重载


因此,重载执行
Num
比重载执行
Num
更加专业化,因此应该明确地首选它。

不是答案,但您可以通过消除第二个重载并使用Zero=Num将
Zero
更改为
,从而消除这种歧义;
@TartanLlama这只是一个玩具代码举例说明问题。