以下所有标准引用均指 N4659: March 2017 post-Kona working draft/C++17 DIS .
考虑以下片段:
#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() {}
static_assert
在 (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++11、C++14、C++17、C++2a)的各种 C++ 语言级别。
问题
我的猜测是这是格式错误的,但无法应用 [temp.class.spec] 的相关部分拒绝它。也许 [temp.class.spec]/8.1 ?
[temp.class.spec]/8.1 The type of a template parameter corresponding to a specialized non-type argument shall not be dependent on a parameter of the specialization. [ Example: [...] — end example ]
最佳答案
据我所知,第一个片段格式不正确(并且需要诊断);由于部分特化 (2),编译器应该拒绝该程序。
[temp.deduct.type]/18适用于此处:
If
P
has a form that contains<i>
, and if the type ofi
differs from the type of the corresponding template parameter of the template named by the enclosing simple-template-id, deduction fails. [...]
标准中的相关示例使用函数模板,但在其他方面非常相似。
所以偏特化(2)的模板实参永远无法推导出,[temp.class.spec.match]/3适用:
If the template arguments of a partial specialization cannot be deduced because of the structure of its template-parameter-list and the template-id, the program is ill-formed.
有趣的是,我找不到诊断此问题的编译器,甚至在严格模式下也找不到 EDG。我们可以推测,大多数编译器作者认为在此处进行诊断的好处不值得为实现检查而付出努力。这可能意味着我们可能会看到以上段落中的要求在 future 从格式错误变为格式错误,不需要诊断。然而,这纯粹是猜测。在任何情况下,我都看不到它会变成格式良好的;我想不出从不匹配的部分特化的有效用途。
[temp.deduct.type]/18的措辞由 CWG2091 决议澄清.
关于c++ - 通过依赖类型使用非类型模板参数的单类型模板参数类模板的部分特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62636822/