13

次のコードでは、可変個引数コンストラクターが2回呼び出されています。必要に応じて、可変個引数コンストラクターの単一引数バージョンの代わりにコピーコンストラクターを呼び出すにはどうすればよいですか?

#include <iostream>

struct Foo
{
    Foo(const Foo &)
    {
        std::cout << "copy constructor\n";
    }

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

    std::string message;
};

int main()
{
    Foo f1;
    Foo f2(f1); // this calls the variadic constructor, but I want the copy constructor.
}
4

2 に答える 2

14

これは、コンストラクターが可変個引数であるという事実とは実際には何の関係もありません。非可変コンストラクターテンプレートを持つ次のクラスは、同じ動作を示します。

struct Foo
{
    Foo() { }

    Foo(const Foo& x)
    {
        std::cout << "copy constructor\n";
    }

    template <typename T>
    Foo(T&& x)
    {
        std::cout << "template constructor\n";
    }

};

問題は、コンストラクターテンプレートの方が一致していることです。コピーコンストラクターを呼び出すには、非const左辺値をにバインドするための修飾変換が必要ですf1const Foo&const修飾を追加する必要があります)。

コンストラクターテンプレートを呼び出すために、変換は必要ありません。 これは、参照が折りたたまれた後(-> )、パラメータータイプを与えるTと推定できます。Foo&Foo& &&Foo&xFoo&

これを回避するには、非定数左辺値参照パラメーターを持つ2番目のコピーコンストラクターを提供しますFoo&

于 2012-06-14T16:48:11.840 に答える
6

const Foo&従来のコピーコンストラクターに加えて、完全一致のオーバーロード、つまり非のオーバーロードを提供するだけです。次に、明示的なキャストを介して呼び出しを委任できます。

Foo(Foo& other) : Foo{const_cast<Foo const&>(other)} { }
于 2012-06-14T16:46:17.507 に答える