为何C++模板代码在GCC编译通过但Visual Studio报C2244错误
问题原因
这是MSVC(Visual Studio配套的C编译器)的已知模板解析缺陷,你的代码完全符合C标准规范,因此GCC、Clang(CLion默认使用的编译器)都可以正常编译。
MSVC在匹配模板类外定义的成员函数签名时,对依赖当前模板参数的非类型模板参数的解析逻辑存在bug:你在类内声明List函数时,std::array的第二个参数直接写的是NUMBER,等价于MyTemplate<E>::NUMBER,但MSVC无法把类外定义里显式写的MyTemplate<E>::NUMBER和类内声明的NUMBER正确关联,因此抛出error C2244报错,认为你定义的函数没有对应的声明。
可行的修复方案
你可以选择以下任意一种方案兼容MSVC的编译:
- 方案1:直接把
List函数的实现写在模板类内部,避开类外定义的签名匹配问题
template<typename E> class MyTemplate { public : static const int NUMBER = static_cast<int>(E::MAX); std::array<int, NUMBER> List() { return std::array<int, NUMBER>(); } };
- 方案2:把类外定义的返回值改成尾置返回类型,帮助MSVC识别签名匹配关系:
template<typename E> auto MyTemplate<E>::List() -> std::array<int, MyTemplate<E>::NUMBER> { return std::array<int, MyTemplate<E>::NUMBER>(); }
- 方案3:将类内的
static const int NUMBER改为static constexpr int NUMBER,部分新版本MSVC对constexpr常量的模板解析逻辑更完善,也可以解决匹配问题:
template<typename E> class MyTemplate { public : static constexpr int NUMBER = static_cast<int>(E::MAX); std::array<int, NUMBER> List(); };
内容的提问来源于stack exchange,提问作者c z
相关产品推荐
相关产品推荐

