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;

テンプレートに対して typedef できないという制限 (C++ 11 で軽減) があることは知っていますが、ここで実行しているのはそのようなものではないと思います。そうしないと、typedefparent_identity_metaが失敗します。独自のクラス定義内にない場合はテンプレートchildを参照し、それ自体から生成されたクラスを参照しているようです。

これはかなり理解できます (child<V>毎回書かなければならないのは苦痛です)。しかし、この動作を無効にする方法はありますか?

4

1 に答える 1

6

ここがC++03とC++11の違うところです。規格の関連部分は[temp.local]/1. C++03 では、これは次のように述べています。

通常の (非テンプレート) クラスと同様に、クラス テンプレートには注入されたクラス名 (節 9) があります。注入されたクラス名は、テンプレート引数リストの有無にかかわらず使用できます。これを template-argument-list なしで使用すると、injected-class-name の後に <> で囲まれたクラス テンプレートの template-parameters が続きます。template-argument-list とともに使用すると、指定されたクラス テンプレートの特殊化 (現在の特殊化または別の特殊化である可能性があります) を参照します。

これは、child(テンプレート引数なしで)特殊化を参照することを意味しchild<V>ます。C++11 では、次のように変更されました。

通常の (非テンプレート) クラスと同様に、クラス テンプレートには注入されたクラス名 (第 9 節) があります。注入されたクラス名は、テンプレート名または型名として使用できます。template-argument-list と一緒に使用する場合、テンプレート template-parameter の template-argument として使用する場合、またはフレンド クラス テンプレート宣言の精巧な型指定子の最終識別子として使用する場合は、クラス テンプレート自体を参照します。 . それ以外の場合は、テンプレート名の後に <> で囲まれたクラス テンプレートのテンプレート パラメータが続きます。

特に注意してください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 に答える