10

非常にあいまいなタイトルで申し訳ありません.(私の英語力がないため). より良いタイトルを提案してください。

次のコードを検討してください。

struct A {
    typedef std::vector<double> State;

    //  template <class... Args>
    //  A(Args... args)
    //      : a(args...)
    //  {}

    template <class... Args>
    A(Args&&... args)
            : a(std::forward<Args>(args)...)
    {}

    A(const A&) = default;
    A(A&&) = default;

    State a;
};

int main(){

    A a(3,2);
    A b = a; // This line triggers an error!!
}

Gcc 4.8.0 はコンパイルに失敗し、エラー メッセージが表示され error: no matching function for call to 'std::vector<double>::vector(A&)' : a(std::forward<Args>(args)...)ました。

このコードが間違っている理由がわかりません。私の意見では、コンパイラは行でコピー コンストラクタを呼び出す必要がありますA b = a;

ただし、コンストラクターをコメント化されたもの (単に値を取る) に置き換えると、コンパイルします。さらに、デフォルトのコピー (および移動) コンストラクターの行が不要になりました。そこで何が起こるの?

4

2 に答える 2

9

C++11 では、(テンプレート化されたコンストラクターで行う必要があるように) コンパイラーが自動的にテンプレート パラメーターを推測&&し、型に適用するとユニバーサル参照が作成されます。これは、左辺値参照か右辺値参照かに関係なく、任意の cv 修飾を持つ任意の型に一致します。

したがって、あなたの場合A、 、したがってArgs...= A &Args &&...=を渡しています。A & &&これは、コンパイラが constness を非 const 変数に追加する必要がないため、A &よりも一致する参照崩壊ルールのおかげです。const A &

于 2013-06-06T02:36:46.673 に答える
3

この場合、const 以外の値を取るため、テンプレート コンストラクターの方が適していると思います。それに変更aするconstと、コピーコンストラクターが呼び出されます...

const A a(3,2);
A b = a;
于 2013-06-06T02:33:33.970 に答える