使用integer_sequence特化模板:GCC与MSVC编译差异问题
问题分析与解决方案
这个问题的核心是模板特化的参数匹配规则以及std::integer_sequence的类型要求,GCC和MSVC在这里的差异源于对C++标准的严格执行程度不同。
问题根源
先看你编写的A的特化代码:
template<int... Ns> struct A<std::integer_sequence<IType, Ns...>> { using type = bool; };
这里你把特化的参数包Ns的类型固定成了int,但C++标准明确规定:std::integer_sequence<T, Ns...>中的Ns...必须是**T类型的编译期常量**:
- 当
IType是int时,std::make_integer_sequence<int, 3>生成的是std::integer_sequence<int, 0,1,2>,参数包Ns是int类型,刚好匹配特化的int... Ns,所以两款编译器都能正常编译。 - 当
IType是long时,std::make_integer_sequence<long, 3>生成的是std::integer_sequence<long, 0L,1L,2L>,参数包元素是long类型,而你的特化只接受int类型的参数包。GCC严格遵循标准,拒绝这种不匹配的情况;而MSVC做了宽松处理(允许整数类型的隐式转换),所以能编译通过。
修复方案
把特化的参数包类型改成和IType一致,让它能适配IType的任意整数类型:
#include <utility> typedef long IType; template<typename> struct A; // 将int... Ns改为IType... Ns,匹配integer_sequence的元素类型 template<IType... Ns> struct A<std::integer_sequence<IType, Ns...>> { using type = bool; }; using B = typename A<std::make_integer_sequence<IType, 3>>::type; int main() { B b; }
这样不管IType是int、long还是其他整数类型,特化的参数包类型都能和std::integer_sequence的元素类型完全匹配,两款编译器都能正常编译。
内容的提问来源于stack exchange,提问作者Dmitry Bezer
相关产品推荐
相关产品推荐

