如何从类自定义中引用类模板作为模板?

时间:2012-10-10 01:16:13

标签: c++ templates

以下是该方案:

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中减轻了)你不能对模板进行类型化,但我不认为这是我在这里遇到的,否则parent_identity_meta中的typedef会失败的。似乎child在不在其自己的类定义内部时引用模板,并且从内部生成

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

1 个答案:

答案 0 :(得分:5)

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

  

与普通(非模板)类一样,类模板具有注入类名(第9节)。 inject-name-name可以使用或不使用template-argument-list。如果在没有template-argument-list的情况下使用它,它等同于inject-name-name,后跟&lt;&gt;中包含的类模板的template-parameters。当它与template-argument-list一起使用时,它引用指定的类模板特化,可以是当前的特化或其他特化。

这意味着child(没有任何模板参数)引用了专门化child<V>。在C ++ 11中,它被改为:

  

与普通(非模板)类一样,类模板具有注入类名(第9节)。 inject-class-name可以用作模板名称或类型名称。当它与template-argument-list一起使用时,作为模板模板参数的模板参数,或作为友元类模板声明的详细类型说明符中的最终标识符,它引用类模板本身。否则,它等同于模板名称,后跟包含在&lt;&gt;中的类模板的模板参数。

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