20

次のC++プログラムを検討してください

#include<map>
#include<iostream>
int main() {
    int a = 5, b = 7;
    auto pair = std::make_pair<int, int>(a,b);
    return 0;
    }

VC11とgcc-4.7.2の使用は、さまざまなエラーで失敗しますが、関連しているようで、VC11エラーメッセージの方が意味があります。

You cannot bind an lvalue to an rvalue   

この失敗から私が理解しているのは

  1. VC11と私は、gcc-4.7.2にはmake_pair(_Ty1&& _Val1, const _Ty2& _Val2)、右辺値参照のみを受け入れることができるstd::make_pairの実装が1つしかないことを想定しています。以前のVC++バージョンの例VC10には2つのバージョンがあり、1つは左辺値を受け入れ、もう1つは右辺値参照を受け入れます。
  2. 右辺値参照を使用して非定数参照を初期化することはできません。つまりint & a = b * 5、無効です。
  3. を参照std::moveに変換するために使用できたので、呼び出しは成功します。lvaluervalue
  4. パラメータごとに2つの異なるタイプを受け入れるためstd::make_pair、考えられるすべての場合のテンプレート引数解決でパラメータのタイプを解決でき、タイプを明示的に指定する必要はありません。

このシナリオは些細なことのように思われ、明示的な型の指定を削除して次のように定義することで、非互換性を簡単に解決できます。

auto pair = std::make_pair(a,b);
  • さて、私の質問は、ライブラリから左辺値の実装を削除するための推進要因は何ですか?
  • 同様の方法で変更された他のライブラリ関数を知ることは可能ですか?
  • g ++、CC、aCC、XL C ++などの複数のコンパイラーをターゲットにする必要がある場合にこれらの状況を処理する方法。コンパイラーがアップグレードされていないか、コンパイラーが右辺値参照や移動セマンティクスをサポートしていません。
4

2 に答える 2

22

std::make_pair 型の名前を入力しないように型の推論を利用することを唯一の目的として存在します。そのため、オーバーロードは1つだけです(VCが考えるように、constへの1つのユニバーサル参照と左辺値参照ではなく、 2つのユニバーサル参照が必要です)。

template <class T1, class T2>
constexpr pair<V1, V2> make_pair(T1&& x, T2&& y);

型を明示的に入力する場合は、ペアコンストラクターを使用できます。さらに短いです...

auto pair = std::pair<int, int>(a,b);
于 2013-01-31T10:58:16.813 に答える
18

するとstd::make_pair<int, int>、テンプレート引数が強制されT1T2両方が として推定されintます。これにより、 のような関数が得られますstd::pair<int,int> make_pair(int&&, int&&)。現在、これらの引数は右辺値参照であるため、右辺値のみを取ることができます。

ただし、 と の型がT1テンプレートT2型推定によって推定される場合、それらは「ユニバーサル参照」として機能します。つまり、左辺値引数を受け取った場合は左辺値参照になり、右辺値引数を受け取った場合は右辺値参照になります。これによりmake_pair、完全な転送を行うことができます。

つまり、テンプレート型の引数を明示的に指定しないでください。の要点はmake_pair、型自体を推測することです。タイプに名前を付けると、完全な転送を行うことができなくなり、左辺値引数に対して失敗します。

于 2013-01-31T11:01:46.777 に答える