希望了解为什么下面的代码会产生以下结果:
类模板部分特化并不比主模板更特化
template <typename T, std::integral... Us>
struct foo : std::false_type {};
template <std::integral T, std::integral... Us>
struct foo<T, Us...> : std::true_type {};
显然,它基于第一个模板参数更加专业,无论剩余的可变参数是否通过
std::integral
概念受到限制。
事实上,如果我们从
Us
中删除限制,专业化就会按预期发生:
template <typename T, typename... Us>
struct foo : std::false_type {};
template <std::integral T, typename... Us>
struct foo<T, Us...> : std::true_type {};
如果我们使用单个
U
,即使存在约束,情况也是如此:
template <typename T, std::integral U>
struct foo : std::false_type {};
template <std::integral T, std::integral U>
struct foo<T, U> : std::true_type {};
我找到了一种在功能上与相关代码等效的解决方法:
template <typename T, std::integral... Us>
struct foo : std::false_type {};
template <std::integral T>
struct foo<T> : std::true_type {};
template <std::integral T, std::integral U, std::integral... Us>
struct foo<T, U, Us...> : std::true_type {};
godbolt 链接用于使用上面的代码进行实验:https://godbolt.org/z/9Tn1KeKnK
这是一个错误吗?
您遇到了一个编译器错误,令人惊讶的是 GCC 和 clang 都有这个错误。相关的写法是这样的:
当
至少与D1
一样受约束,并且D2
至少不与D1
一样受约束时,声明D2
比另一个声明D2
受到更多约束。D1
此外,[temp.func.order] p6.4 指出:
完整的定义有些复杂,但显然,具有约束
std::integral<T>
使得部分特化比主模板受到更多约束,而主模板没有这样的约束。 更正式地说,主模板约束的析取范式为:
std::integral<U1> && std::integral<U2> && ...
部分专业化约束的析取范式为:
std::integral<T> && std::integral<U1> && std::integral<U2> && ...
后一个DNF是前一个DNF加上一个附加约束,因此,后者包含
前者。 部分专业化受到更多限制,因此更加专业化。 编译器错误
。只有 GCC 和 clang 无法编译。 您的解决方法(版本 2 到 3)都不是必要的。