c++ - C++ 中模板化子类专门化的限制

标签 c++ templates subclass template-specialization

假设我们有代码:

Try it online!

template <int Size>
struct A {
    template <typename T, typename Enable = void> struct B;
    template <> struct B<bool, std::enable_if_t<Size >= 1>> {};
    template <> struct B<short, std::enable_if_t<Size >= 2>> {};
};

template <int Size>
struct D {
    template <typename T> struct E;
    template <> struct E<bool> {};
    template <> struct E<short> {};
};

template <int Size>
struct F {
    template <typename T> struct G {};
};

template <int Size, typename T, typename Enable = void> struct C;
template <int Size> struct C<Size, bool, std::enable_if_t<Size >= 1>> {};
template <int Size> struct C<Size, short, std::enable_if_t<Size >= 2>> {};

结构 C 和 F 在所有 CLang/GCC/MSVC 中编译良好。 Struct D 在 CLang/MSVC 中编译良好,但在 GCC 中编译错误。结构体 A 不能被所有 CLang/GCC/MSVC 编译。

GCC 对 D 的错误(与 A 类似):

<source>:19:15: error: explicit specialization in non-namespace scope 'struct D<Size>'
   19 |     template <> struct E<bool> {};

CLang 对 A 的错误:

type_traits:2514:44: error: no type named 'type' in 'std::enable_if<false>'; 'enable_if' cannot be used to disable this declaration
    using enable_if_t = typename enable_if<_Cond, _Tp>::type;

MSVC 的 A 错误:

<source>(11): error C2938: 'std::enable_if_t<false,void>' : Failed to specialize alias template
<source>(11): note: see reference to alias template instantiation 'std::enable_if_t<false,void>' being compiled
<source>(30): note: see reference to class template instantiation 'A<1>' being compiled
<source>(11): error C2913: explicit specialization; 'A<1>::B' is not a specialization of a class template

我有几个问题:

  1. std C++ 中是否允许专门化模板子类?有什么限制?看起来 GCC 根本不允许,而 CLang/MSVC 允许,但有一定限制。

  2. 是否允许拥有模板化子类。如果允许的话我该如何专门化它?也许它们允许一些类外的特化(那么语法是什么)?

  3. 如果不允许专门化模板化子类,那么至少允许有完全定义的模板化子类(没有专门化)?看起来上面的 struct F 使用完全定义的模板化子类并且在任何地方都可以很好地编译。

最佳答案

  1. 为什么A不起作用

您可以注意到AF之间的区别,std::enable_if使用Size进行检查,但它是类模板A的模板参数,而不是内部模板B本身的模板参数。如果您像 F 那样添加一个,那么它就会起作用。例如

template <int Size>
struct A {
    template <int S = Size, typename T = void, typename Enable = void> struct B;
    template <int S> struct B<S, bool, std::enable_if_t<S >= 1>> {};
    template <int S> struct B<S, short, std::enable_if_t<S >= 2>> {};
};
  • 为什么 Gcc 不能与 D 一起使用
  • 这似乎是一个gcc's issue ,根据CWG 727 ,显式特化可以在任何范围内声明,包括在类定义中。

    An explicit specialization may be declared in any scope in which the corresponding primary template may be defined (10.3.1.2 [namespace.memdef], 12.2 [class.mem], 17.6.2 [temp.mem]).

    关于c++ - C++ 中模板化子类专门化的限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67916281/

    相关文章:

    c++ - OpenCL 内置函数选择

    c++ - 在 CComboBox (MFC) 中通过文本设置选择

    c++ - 具有特定类型作为泛型参数的 STL 容器

    c++ - SFML 粒子系统架构

    wordpress - 如何让 WordPress 识别我新创建的页面模板?

    c++ - 确定 uint32_t 的字节顺序

    c++ - 在类的所有方法中访问变量的方式,除了定义为全局变量

    Swift:覆盖也是父类属性类的子类的子类属性

    java - 使用子类对象修改其父类(super class)对象中的 protected 属性

    Java:如何拥有子类类型的数组?