c++ - 函数模板重载解析在 Visual C++ 2017 中失败

标签 c++ templates visual-c++ c++14

我想弄清楚我写的是不是合法的 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/

相关文章:

visual-c++ - 如何在Visual C++中配置opencv 1.2?

c++ - 如何根据结构的字段之一对结构指针列表进行排序?

c++ - _msize 调试断言失败

c++ - 尝试使用外部 header 编译程序时出现问题

c++ - 如何移动 3D 框以保持在旋转平面上?

c++ - 解析缓冲区 C - 前进缓冲区过去的空白,存储字

c++ - 使用参数类型的值在尾随返回中需要 decltype

c++ - 一个默认的默认构造函数,为什么不是用户提供的默认构造函数呢?

c++ - 如何在编译期间计算数组大小(不接受指针)?

templates - 错误 : "invalid type for comparison" in revel template