首页 > 解决方案 > 在类中使用成员类模板特化

问题描述

是否有在同一个类中使用成员类模板专业化的标准兼容方式?

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 版本。

标签: c++c++17

解决方案


是否有在同一个类中使用成员类模板专业化的标准兼容方式?

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

C++17直接声明

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

然而,C++14 说

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

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


推荐阅读