在派生类中执行成员模板类的部分类内特化是否合法

W.F*_*.F. 7 c++ templates partial-specialization template-specialization language-lawyer

这是这个问题的延续.如果成员类部分特化是这样的,我特别感兴趣:

struct FooParent {
    template <class>
    struct Bar{ };
};

struct Foo: FooParent {
    template <class T>
    struct Bar<T*> {};
};
Run Code Online (Sandbox Code Playgroud)

我知道这可以在命名空间范围内完成:

template <class T>
struct Foo::Bar<T*>{ };
Run Code Online (Sandbox Code Playgroud)

但我也特别感兴趣的是派生类级别的类内部分特化.

clang和gcc在遇到前者时都会抱怨:

clang声明有明确的模板专业化,显然不会发生:

错误:类范围中'Bar'的显式特化

gcc在这里稍微冗长一点,并说成员模板的特化必须在命名空间范围内执行,这显然不是非派生类的情况.

错误:'template struct FooParent :: Bar'的特化必须出现在命名空间范围内

gcc是否在他的错误消息中?

sky*_*ack 1

我正在尝试按照OP的要求总结我在问题评论中所说的话。


我想[temp.class.spec]/5足以回答这个问题。
尤其:

类模板部分特化可以在任何可以定义相应主模板的命名空间范围中声明或重新声明[...]。

在这种情况下,实际的规则是可以定义主模板的位置。
在示例中,您尝试在派生类中声明(并根据上下文定义,但它首先是声明)部分特化。

简短的答案是:您不能在派生类中定义主模板,因此也不能在该类中声明部分特化。

如果可能的话,以下内容也将成为可能:

struct FooParent {
    template <class>
    struct Bar;
};

struct Foo: FooParent {
    template <class T>
    struct FooParent::Bar<T*> {};
};
Run Code Online (Sandbox Code Playgroud)

或者如果您愿意的话,可以选择这个:

struct Foo: FooParent {
    template <class T>
    struct Bar<T*> {};
};
Run Code Online (Sandbox Code Playgroud)

不幸的是(?)它们是不允许的,这足以告诉您,您专门化类模板的尝试也是无效的。

无论如何,让我们进一步考虑一下。
主模板是成员规范的一部分Foo(请参阅此处了解更多详细信息)。
因此,问题是 -我在哪里可以定义这样的模板?,很快就会变成 -我在哪里可以定义班级的任何其他成员?
同样,答案是——不在派生类的范围内


我很确定语言律师会给你更直接和直接的解释。
我也很确定同一个语言律师会因为我提到了标准的错误部分而咒骂我。
不管怎样,我希望上面的几个例子能给你一个开始的基点。