c++ - 通过依赖类型使用非类型模板参数的单类型模板参数类模板的部分特化

标签 c++ language-lawyer

以下所有标准引用均指 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++ 语言级别。
问题
  • 上面的第一个片段实际上格式错误(不需要诊断?),还是 GCC 或 Clang 错误?

  • 我的猜测是这是格式错误的,但无法应用 [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 of i 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/

    相关文章:

    c++ - std::tuple 内存对齐

    c++ - 将 C++ 对象传递给它自己的构造函数是否合法?

    c - 什么是 "abstract semantics"和 "actual semantics"?

    c++ - C++控制网络摄像机的云台功能

    c++ - C 标准库可扩展性对 C++ 程序有多大影响?

    c++ - 转发声明 C 标准库实体而不是 C++ 标准库实体是否合法?

    c++ - 如何在 'C' 之前释放 Ctrl 时使用 Qt 捕获 Ctrl+C 键事件?

    c++ - 什么是邻接表?如何编写邻接表?

    c++ - g++4.4 c++98 目标文件是否与 g++4.8 c++11 兼容?

    c++ - 将值插入到 vector<entry> 的映射中