最近的 MSVC 中的 C++ 模板解析错误,GCC、LLVM 和较旧的 MSVC 正常

标签 c++ templates visual-c++ compiler-bug

这里是一些 C++ 模板函数,在一般情况下,它调用其特化之一。

最近将 Microsoft Visual Studio 升级到 17.5.4 (MSVC 19.35.32217) 后,编译下面的源代码会产生以下编译错误:

bugtemplate.cpp(8,43): Error C2672: 'Test': no matching overloaded function found
Bugtemplate.cpp(6,12): message : could be 'INT Test(size_t)'
bugtemplate.cpp(9,1): message : 'INT Test(size_t)': could not deduce template argument for '__formal'
bugtemplate.cpp(8,43): message : 'Test': function declaration must be available as none of the arguments depend on a template parameter

相同的代码可以使用所有最新版本的 GCC 和 LLVM 进行编译。它还使用 MSVC 19.34.31944(GitHub CI/CD 中的当前编译器)进行编译。该代码改编自一个更大的项目,该项目在 Linux、Windows、macOS 和 *BSD 上编译了多年。

源代码:

#include <iostream>
#include <cstdint>

// General template
template<typename INT, typename std::enable_if<std::is_integral<INT>::value>::type* = nullptr>
inline INT Test(size_t x)
{
    return static_cast<INT>(Test<uint64_t>(x));
}

// Template specialization.
template<> uint64_t Test<uint64_t>(size_t x)
{
    return 0;
}

int main()
{
    std::cout << Test<int>(0) << std::endl;
}

对于所有 C++ 专家来说,这是最新的 MSVC 中的一个新错误,还是迄今为止所有其他编译器都没有注意到的无效 C++ 代码?

最佳答案

这似乎是 msvc bug因为它接受 C++17 中的代码,但拒绝 C++20 中的代码。 Demo .

另请注意,如果您对函数模板使用单独的声明和定义(如答案末尾所示),则 msvc 会开始接受代码。


这是错误:

MSVC rejects valid code with c++20


解决方案

适用于 msvc 的一种解决方法是使用单独的声明,如下所示:

// declaration for primary template
template<typename INT, typename std::enable_if<std::is_integral<INT>::value>::type* = nullptr>
inline INT Test(size_t x);

template<typename INT, typename std::enable_if<std::is_integral<INT>::value>::type*>
inline INT Test(size_t x)
{
    return static_cast<INT>(Test<uint64_t>(x));
}
// Template specialization.
template<> uint64_t Test<uint64_t>(size_t x)
{
    return 0;
}

works now

关于最近的 MSVC 中的 C++ 模板解析错误,GCC、LLVM 和较旧的 MSVC 正常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76147272/

相关文章:

c++ - 从派生指针调用虚函数而不支付 vtable 价格

c++ - 获取当前按键的简单方法

c++ - 具有私有(private)/删除的默认构造函数的参数类型

C++ - 有没有办法让模板类特化包含通用模板中的代码?

c - 如何在 Visual C++ Express 中运行 .lib 项目中的单个 .c 文件?

c - 从C语言的命令窗口读取文件

c++ - 使用用户输入 C++ 创建 n 个不同的 vector

C++ 编译时类型检查

c++ - 如何在字符串 vector 中找到某个值

python - 在 Python/Django 中使用 Memcached - 问题