我试图弄清楚我写的是法律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,以查看编译失败。海湾合作委员会和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 的旧方言...因此,用一粒盐来采取推理。但是,由于您仅向模板提供一个参数,而第二个模板需要两个参数,即VC 编译器正在尝试使用第一个模板,因为它具有默认参数,并且只能采用一个参数。因此,它选择了该模板,但不能从ENUM1转换为Enum0。