2

これは一言では言い表せません。ときどき、次のようなクラスを見かけます。

template <typename T>
class Wrapper
{
public:
    Wrapper(const T& t) : t_(t) {}
    Wrapper(const Wrapper& w) : t_(w.t_) {}
private:
    T t_;
}

私が知る限り、これは正当なコードです。ただし、コピー コンストラクターが をconst Wrapper&必要とすることを明示的に指定せずにを受け入れることができるのはなぜですかconst Wrapper<T>&。テンプレートの種類が暗示されるのは、他にどのような場合ですか? クラス内定義を使用しない場合、この方法でコピー コンストラクターを記述できますか?

4

4 に答える 4

3

基本的に、クラステンプレート定義内では 、完全にパラメーター化されたバージョンのtemplate-idの省略形として定義されているテンプレートのtemplate-nameを使用できます。

于 2009-11-09T22:29:08.447 に答える
3

14.6.1/1 の言語標準で明示的に指定されています。

クラス テンプレートのスコープ内で、テンプレートの名前が修飾されておらず、< が続いていない場合、テンプレートの名前の後に <> で囲まれたテンプレート パラメータが続いたものと同等です。

これは、標準の後のバージョンで (「注入されたクラス名」の概念を通じて) 言い直されましたが、ポイントは、この動作がドキュメントで明示的に綴られていることです。

質問の 2 番目の部分に答えるために、この規則は、クラス外のメソッド定義を記述するときのパラメーター宣言にも適用されますが、戻り値の型宣言には適用されません。たとえば、このコードはOKです

template <typename T> struct S {
  S foo(S);
};

template <typename T> S<T> S<T>::foo(S s) {
  /* whatever */
}

<T>ただし、メソッドの定義で戻り値の型からビットを削除することはできません。<T>(また、メソッドの修飾名から削除することはできません。)

具体的には、コンストラクター<T>に関しては、クラスの完全な名前 (を含む) を使用する必要があります<T>が、コンストラクター自体の名前には使用しないでください。したがって、あなたの場合のクラス外定義の最短形式は次のようになります

template <typename T> Wrapper<T>::Wrapper(const Wrapper& w) : t_(w.t_)
{
}

<T>コンストラクタ名にビットを追加したい場合でも、ビットを追加できないことに注意してください。

template <typename T> Wrapper<T>::Wrapper<T>(const Wrapper& w)
                                         ^ ERROR !!!

PS この最後の主張については、さらなる調査が必要です。Comeau Online コンパイラはエラーと判断しますが、GCC は問題ないと判断します。後で戻ってきます。

PPS MSVC++ 2005 のコンパイラは、後者の宣言について警告を表示します

warning C4812: obsolete declaration style: please use 'Wrapper<T>::Wrapper' instead

面白い...

于 2009-11-09T22:40:37.893 に答える
0

いいえ、クラス外では次のように書く必要があります。

template <typename T>
Wrapper<T>::Wrapper<T>(const Wrapper<T>& w) : t(w.t) {}

しかし、クラス内Wrapperでは、「現在のクラス」の代わりになります。

編集:これは、Andrewと、コンパイラがコンストラクタでを拒否する理由についての彼の調査のためです。

template <typename T>
class Foo {
public:
    Foo() {}
    Foo(const Foo& f);
};

template <typename T>
Foo<T>::Foo<T>(const Foo<T>& f) { }

int main(int argc, char** argv)
{
    Foo<int> f;
    Foo<int> g(f); // make sure the template is instantiated
}
于 2009-11-09T22:52:19.070 に答える
0

このようなテンプレート化されたクラス内で、クラスの名前を使用することは、を使用することと同じWrapper<T>です。

于 2009-11-09T22:30:11.483 に答える