l値をstd :: make_pairに渡す方法

Aug 16 2020

std::make_pair 一つだけの実装C ++ 14以降があります

テンプレート<クラスT1、クラスT2> constexpr std :: pair <V1、V2> make_pair(T1 && t、T2 && u);

両方のパラメータはR値の参照であるとに応じて、この

R値の参照をl値で初期化することはできません。

    int i = 1;
    char ch = 'a';
    std::unordered_map<int, char> mp;
    mp.insert(make_pair<int,char>(i, ch));

したがって、上記のコードのようにmake_pairを使用しようとすると、正しくエラーがスローされますerror: cannot bind rvalue reference of type 'int&&' to lvalue of type 'int'

ただし、テンプレート引数を削除して次のように呼び出すと、上記のコードでは完全に機能します。

mp.insert(make_pair(i, ch));

これがどのように機能するのか混乱しておりichどちらもL値です。テンプレート引数の解決はL値をR値に変換しますか、それともこれはどのように機能しますか?

回答

3 songyuanyao Aug 16 2020 at 08:06

のパラメータはmake_pair右辺値参照として宣言されていませんが、転送参照として宣言されています。

転送参照は、関数の引数の値カテゴリを保持する特別な種類の参照であり、std :: forwardを使用して転送することができます。転送参照は次のいずれかです。

  1. 同じ関数テンプレートのcv非修飾型テンプレートパラメーターへの右辺値参照として宣言された関数テンプレートの関数パラメーター:

転送参照は、テンプレート引数の推論の助けを借りて、左辺値と右辺値の両方で機能します。左辺値が渡されると、テンプレートパラメーターは左辺値参照として推定されます。参照が折りたたまれた後、関数パラメーターも左辺値参照になります。右辺値を渡す場合、テンプレートパラメーターは非参照として推定され、関数パラメーターは右辺値参照です。

一方、のようにテンプレート引数を明示的に指定するmake_pair<int,char>(...)と、関数パラメーターはそれに応じて右辺値参照になります。

1 JaMiT Aug 16 2020 at 11:01

songyuanyaoによって答えはすでに何が起こっているかのほとんどを説明しています。ただし、明示的なテンプレート引数を使用してこれを機能させる方法に貢献したいと思います。あなたはほとんどそこにいましたが、最後の一歩を踏み出しませんでした。

これがどのように機能するのか混乱しておりichどちらもL値です。

丁度。テンプレート引数で指定できるl値が必要です。

std::make_pair<int &, char &>(i, ch)

または、より多くの場合に機能するフォーム:

std::make_pair<const int &, const char &>(i, ch)

少し余分な記述がありますが、何らかの理由で引数の推論が失敗した場合に必要です。