我想弄清楚我写的是不是合法的 C++14 w.r.t.明确的函数模板重载解析。
在我看来,下面的程序应该编译并返回3
。
各种版本的 Clang 和 GCC 仅在编译时计算(使用 -std=c++14 -O2
),但 Visual C++ 2017(版本 15.5.2;最新更新时间为写作)用下面的错误信息扼杀它。
enum class Enum0 { State };
enum class Enum1 { State };
template <Enum0 Param0 = Enum0::State>
int get()
{
return 1;
}
template <Enum1 Param1>
int get()
{
return 2;
}
int main()
{
int sum = 0;
sum += get(); // should call instantiation of first function template
sum += get<Enum1::State>(); // should call instantiation of second function template
return sum;
}
这是 Visual C++ 编译器发出的错误消息:
20 : <source>(20): error C2668: 'get': ambiguous call to overloaded function
11 : <source>(11): note: could be 'int get<Enum1::State>(void)'
5 : <source>(5): note: or 'int get<Enum0::State>(void)'
20 : <source>(20): note: while trying to match the argument list '()'
参见 https://godbolt.org/g/PhH2VY用于现场演示(和 https://godbolt.org/g/BVEv79 用于编辑问题之前的前一个代码示例)。 将编译器更改为 MVSC 以查看编译失败。 GCC 和 Clang 没有指出任何问题。两者都很好地发出了以下 x86 程序集:
mov eax, 3
ret
GCC 和 Clang 是否过于宽松,或者这是 Visual C++ 的问题?
最佳答案
这是一个很好的问题,不是吗?如果我将第二个调用更改为:
sum += get<Enum1::State, int>(0.0); // should call instantiation of second function template
...然后编译...
注意,我添加了第二个模板参数。在我的日常工作中,我使用与 MFC 兼容的旧 C++ 方言……所以请对我的推理持保留态度。但是,由于您只向模板提供一个参数,而第二个模板需要两个参数,ISTM 认为 VC++ 编译器正在尝试使用第一个模板,因为它具有默认参数并且只能采用一个参数。所以它选择了那个模板,但不能进行从 Enum1 到 Enum0 的转换。
关于c++ - 函数模板重载解析在 Visual C++ 2017 中失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48012478/