3

以下は単純なテンプレートです。

template <class T>
class tt {
    private:
        T  x;
    public:
        tt() {x=0;};
        Add(T p) {x += p;};
};

...そしてそのサブクラス。

class cc : public tt<int> {

    public:
        cc() : tt() {};

};

これは VC では正常にコンパイルされますが、E2102 エラーが発生する C++ Builder (XE) ではコンパイルされません。C++ Builder コンパイラは、コンパイルする cc クラスのコンストラクタで次の構文を必要とします。

cc() : tt<int>() {};

実際、C++ Builder コンパイラは、tt テンプレートが cc クラス内で言及されるたびに繰り返されるテンプレート パラメーターを必要とします。

標準の C++ 仕様では、テンプレート パラメーターを常に繰り返す必要があると指定されていますか? それとも、C++ Builder コンパイラが間違っていますか?

4

2 に答える 2

4

C++ Builder はここで間違っています。コンストラクターのメンバー初期化子リストで祖先の名前を使用できる必要がある理由は、注入されたクラス名の概念に関係しています。

クラスを定義すると、コンパイラはクラスの名前をそのクラスに挿入し、それ自体を参照させます。この注入された名前により、クラス内でテンプレート引数なしでクラスの名前を使用できるようになります。

template <class T>
struct tt {
    // The compiler behaves as if there was the following.
    // typedef tt<T> tt;
};

この挿入された名前ttは、メンバー初期化子リストで名前を使用するときに検索されるものです。

(記録として、clang はテンプレート引数なしのスニペットを受け入れます。)

おまけ:ccテンプレート パラメーターを使用してクラス テンプレートとして定義しT、先祖が に依存していた場合、のコンストラクターのメンバー初期化子リストのコンテキストでT名前ttが見つかりません。cc

template <class T>
class cc : tt<T> {
    cc()
        : tt<T>() /* You must use <T> here. */
    {
    }
};
于 2011-11-01T20:49:25.607 に答える
0

typedef を使用すると、繰り返しを回避できます。

typedef tt<int> tti;

...

class cc : public tti {

    public:
        cc() : tti() {};

};
于 2011-11-01T16:02:39.843 に答える