28

可変引数コンストラクターは、暗黙的に生成されたコンストラクター、つまりデフォルト コンストラクターとコピー コンストラクターを非表示にすることになっていますか?

struct Foo
{
    template<typename... Args> Foo(Args&&... x)
    {
        std::cout << "inside the variadic constructor\n";
    }
};

int main()
{
    Foo a;
    Foo b(a);
}

どういうわけか、この回答を読んだ後、これが何も出力しないことを期待していましたが、g ++ 4.5.0で2回出力inside the variadic constructorされます:(この動作は正しいですか?


可変個引数テンプレートなしでも発生します。

struct Foo
{
    Foo()
    {
        std::cout << "inside the nullary constructor\n";
    }

    template<typename A> Foo(A&& x)
    {
        std::cout << "inside the unary constructor\n";
    }
};

int main()
{
    Foo a;
    Foo b(a);
}

ここでも、両方の行が印刷されます。

4

1 に答える 1

21

暗黙的に宣言されたコピー コンストラクターの宣言は、実際には抑制されていません。オーバーロード解決のルールにより、呼び出されていません。

暗黙的に宣言されたコピー コンストラクターの形式はFoo(const Foo&)です。これの重要な部分は、const 参照を取ることです。コンストラクター テンプレートは非 const 参照を取ります。

aは const ではないため、非 const ユーザー宣言コンストラクター テンプレートは、暗黙的に宣言されたコピー コンストラクターよりも優先されます。暗黙的に宣言されたコピー コンストラクターを呼び出すには、aconstを作成します。

const Foo a;
Foo b(a);

static_castまたは、次への const 参照を取得するために使用できますa

Foo a;
Foo b(static_cast<const Foo&>(a));

これを説明するオーバーロード解決規則は、ほとんどが C++0x FCD の §13.3.3.2/3 にあります。左辺値と右辺値の参照を組み合わせたこの特定のシナリオは、303 ページのさまざまな例で説明されています。


可変引数コンストラクター テンプレートは、ユーザーが宣言し、ユーザーが宣言したコンストラクターがない場合にのみ暗黙的に宣言された既定のコンストラクターが提供されるため、暗黙的に宣言された既定のコンストラクターを抑制します (C++0x FCD §12.1/5)。

class に対してユーザー宣言されXたコンストラクターがない場合、パラメーターを持たないコンストラクターは暗黙的にデフォルトとして宣言されます。

可変引数コンストラクター テンプレートは、非テンプレート コンストラクターのみがコピー コンストラクターになることができるため、暗黙的に宣言されたコピー コンストラクターを抑制しません (C++0x FCD §12.8/2、3、および 8)。

class の非テンプレート コンストラクターは、最初のパラメーターの型が 、、またはであり、他のパラメーターがないか、他のすべてのパラメーターに既定の引数があるX場合、コピー コンストラクターです。X&const X&volatile X&const volatile X&

class の非テンプレート コンストラクターは、最初のパラメーターが、、、またはのいずれかの型であり、他のパラメーターがないか、他のすべてのパラメーターに既定の引数があるX場合、ムーブ コンストラクターです。X&&const X&&volatile X&&const volatile X&&

クラス定義でコピー コンストラクターが明示的に宣言されておらず、ユーザーが宣言した移動コンストラクターがない場合、コピー コンストラクターは暗黙的に既定値として宣言されます。

于 2010-06-01T22:50:37.270 に答える