在类中使用成员类模板特化

时间:2021-03-04 21:28:35

标签: c++ c++17

在同一个类中是否有使用成员类模板特化的符合标准的方法?

struct S {
    template<typename T> struct Data;
    // Explicit (AKA full) template specialization is not allowed here.
    template<> struct Data<char> {};
    template<> struct Data<int> {};

    Data<char> d1;
    Data<int> d2;
};

不起作用,因为类内部不允许成员类模板的完全专业化。在这种情况下,一些编译器选择忽略神圣标准并且对代码感到满意,但有些编译器遵循规则。

struct S {
    template<typename T> struct Data;

    // Specializations are not defined at this point.
    Data<char> d1;
    Data<int> d2;
};

template<> struct S::Data<char> {};
template<> struct S::Data<int> {};

也不起作用,因为在定义之前无法使用专业化。

我知道我可以将成员类模板移出类,但这不是重点。

愚蠢的是,如果我仅仅因为这个原因使用额外的模板参数,我可以解决禁止类内模板专业化的问题:

struct S {
    template<typename T, typename NotUsed = void> struct Data;
    // Now it's a partial template specialization, which is allowed.
    template<typename NotUsed> struct Data<char, NotUsed> {};
    template<typename NotUsed> struct Data<int, NotUsed> {};

    Data<char> d1;
    Data<int> d2;
};

现在可以了,因为类内部允许部分模板特化。

我是否缺少某种“正确方式”的方法——在课堂外进行专业化,但仍然能够在课堂内使用它?我假设标准的 C++17 版本。

1 个答案:

答案 0 :(得分:2)

<块引用>

在同一个类中是否有使用成员类模板特化的符合标准的方法?

是:使用符合 C++17 的编译器。

C++17 directly states

<块引用>

可以在可以定义相应主模板的任何范围内声明显式特化

然而,C++14 says

<块引用>

应在包含专用模板的命名空间中声明显式专业化。

您的编译器似乎遵循 C++14 规则。如果将它显式设置为 C++17(或更高版本)不能修复它,那么这是一个编译器错误。