这里是一些 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;
}
关于最近的 MSVC 中的 C++ 模板解析错误,GCC、LLVM 和较旧的 MSVC 正常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76147272/