6

这是场景:

template <template <typename> class T, typename V>
struct parent {
    void do_something();
};

template <typename V>
struct child : public parent<child, V> {
    void do_something(V argument);
    using parent<child, V>::do_something; // C3200: invalid template argument for template parameter 'IMPL', expected a class template
};

上面的代码无法在给定的行上编译并出现给定的错误(MSVC 9.0)。但是,如果我改写这个,则在类定义之外child

template <typename V>
struct parent_identity_meta {
    typedef typename parent<child, V> type; // no error!
};

我现在可以在以下范围内成功执行以下操作child

using parent_identity_meta<V>::type::do_something;

我知道有一个限制(在 C++11 中有所缓解)你不能对模板进行 typedef,但我认为这不是我在这里遇到的问题,否则 typedef inparent_identity_meta会失败。当不在其自己的类定义中时,它似乎是child模板,并且是从其自身内部生成的类

这是可以理解的(child<V>每次都要写会很痛苦);但是有什么办法可以覆盖这种行为吗?

4

1 回答 1

6

这是C++03和C++11不同的地方。该标准的相关部分是[temp.local]/1. 在 C++03 中,这表明:

与普通(非模板)类一样,类模板有一个注入类名(第 9 条)。注入的类名可以与模板参数列表一起使用,也可以不与模板参数列表一起使用。当它在没有模板参数列表的情况下使用时,它等效于注入的类名称后跟 <> 中包含的类模板的模板参数。当它与模板参数列表一起使用时,它指的是指定的类模板特化,可以是当前特化或另一个特化。

这意味着child(没有任何模板参数)指的是 specialization child<V>。在 C++11 中,它被更改为:

像普通(非模板)类一样,类模板有一个注入类名(第 9 条)。注入的类名可以用作模板名或类型名。当它与模板参数列表一起使用时,作为模板模板参数的模板参数,或作为朋友类模板声明的详细类型说明符中的最终标识符,它指的是类模板本身. 否则,它相当于模板名称后跟 <> 中包含的类模板的模板参数。

特别注意When it is used ... as a template-argument for a template template-parameter ... it refers to the class template itself.。这意味着在 C++11 中,您的代码将是正确的。

于 2012-10-10T01:35:51.770 回答