这是场景:
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
};
Run Code Online (Sandbox Code Playgroud)
上面的代码无法使用给定的错误(MSVC 9.0)在给定的行上进行编译.但是,如果我写这个,在类定义之外child:
template <typename V>
struct parent_identity_meta {
typedef typename parent<child, V> type; // no error!
};
Run Code Online (Sandbox Code Playgroud)
我现在可以在以下内容中成功完成以下操作child:
using parent_identity_meta<V>::type::do_something;
Run Code Online (Sandbox Code Playgroud)
我知道有一个限制(在C++ 11中得到缓解)你不能对模板进行typedef,但我不认为这是我在这里遇到的,否则typedef parent_identity_meta会失败.它似乎是child指模板不在其自己的类定义内部时,以及从内部生成的类.
这是可以理解的(必须child<V>每次写一次都会很痛苦); 但有没有办法覆盖这种行为?
这是C++ 03和C++ 11彼此不同的地方.该标准的相关部分是[temp.local]/1.在C++ 03中,这表明:
与普通(非模板)类一样,类模板具有注入类名(第9节).inject-name-name可以使用或不使用template-argument-list.如果在没有template-argument-list的情况下使用它,它等同于inject-name-name,后跟<>中包含的类模板的template-parameters.当它与template-argument-list一起使用时,它引用指定的类模板特化,它可以是当前的特化或其他特化.
这意味着child(没有任何模板参数)指的是专门化child<V>.在C++ 11中,它被改为:
与普通(非模板)类一样,类模板具有注入类名(第9节).inject-class-name可以用作模板名称或类型名称.当它与template-argument-list一起使用时,作为模板模板参数的模板参数,或作为友元类模板声明的详细类型说明符中的最终标识符,它引用类模板本身.否则,它等同于template-name,后跟<>中包含的类模板的template-parameters.
请特别注意When it is used ... as a template-argument for a template template-parameter ... it refers to the class template itself..这意味着在C++ 11中,您的代码是正确的.