All standard references below refers to N4659: March 2017 post-Kona working draft/C++17 DIS https://timsong-cpp.github.io/cppwp/n4659/.
考虑以下片段:
#include <type_traits>
template <int N> struct num {};
template <typename> struct A;
// (1)
template <int N> struct A<num<N>> { using type = bool; };
// (2)
template <long N> struct A<num<N>> { using type = char; };
static_assert(!std::is_same_v<long, int>, "");
// (A)
static_assert(std::is_same_v<A<num<1>>::type, bool>, "");
int main() {}
The static_assert
at (A)对于 GCC 成功,但对于 Clang 失败:
error: static_assert failed due to
requirement 'std::is_same_v<char, bool>' ""
本质上,GCC 选择完美匹配的专业(1),而 Clang 选择专业(2).
类似地,如果我们删除断言和专业化(1):
template <int N> struct num {};
template <typename> struct A;
// (2)
template <long N> struct A<num<N>> { using type = char; };
int main() {
A<num<1>> a{};
(void)a;
}
然后 GCC 无法编译该程序,而 Clang 接受它。
GCC:
error: variable '`A<num<1> > a`' has initializer but incomplete type
此行为适用于各种 GCC 和 Clang 版本,以及这些版本上的各种 C++ 语言级别(C++11、C++14、C++17、C++2a)。
Question
- 上面的第一个片段实际上是格式错误的(不需要诊断吗?),还是 GCC 或 Clang 错误?
我的猜测是,这是格式错误的,但无法应用的相关部分[温度等级规格] https://timsong-cpp.github.io/cppwp/n4659/temp.class.spec拒绝它。也许[温度等级规格]/8.1 https://timsong-cpp.github.io/cppwp/n4659/temp.class.spec#8.1?
[温度等级规格]/8.1与专门化的非类型参数相对应的模板参数的类型不应依赖于专门化的参数。 [示例:[...] — 示例结束 ]