¿Cómo se pueden pasar los valores l a std :: make_pair?

Aug 16 2020

En std::make_pair solo hay una implementación C ++ 14 en adelante

plantilla <clase T1, clase T2> constexpr std :: par <V1, V2> make_pair (T1 && t, T2 && u);

Ambos parámetros son referencias de valor R y de acuerdo con este

Las referencias de valores R no se pueden inicializar con valores l.

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

Entonces, cuando trato de usar make_pair como en el código anterior, arroja un error correctamente error: cannot bind rvalue reference of type 'int&&' to lvalue of type 'int'.

Sin embargo, funciona perfectamente para el código anterior si cambio, suelto los argumentos de la plantilla y lo llamo como

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

Estoy confundido de cómo funciona esto iy chambos son valores L. ¿La resolución del argumento de la plantilla convierte los valores L en valores R o le gusta cómo funciona esto?

Respuestas

3 songyuanyao Aug 16 2020 at 08:06

Los parámetros de make_pairno se declaran como rvalue-reference, sino como referencia de reenvío .

Las referencias de reenvío son un tipo especial de referencias que preservan la categoría de valor de un argumento de función, lo que hace posible reenviarlo mediante std :: forward. Las referencias de reenvío son:

  1. parámetro de función de una plantilla de función declarada como referencia rvalue al parámetro de plantilla de tipo cv-no calificado de esa misma plantilla de función:

La referencia de reenvío funciona tanto con lvalues ​​como con rvalues, con la ayuda de la deducción de argumentos de plantilla . Cuando se pasa un lvalue, el parámetro de plantilla se deducirá como lvalue-reference, después de colapsar la referencia, el parámetro de la función también es lvalue-reference. Al pasar un rvalue, el parámetro de plantilla se deduciría como no referencia, el parámetro de función es rvalue-reference.

Por otro lado, si especifica el argumento de plantilla explícitamente como make_pair<int,char>(...), el parámetro de la función se convierte en rvalue-reference en consecuencia.

1 JaMiT Aug 16 2020 at 11:01

La respuesta de songyuanyao ya explica la mayor parte de lo que está sucediendo. Sin embargo, me gustaría contribuir a cómo hacer que esto funcione con argumentos de plantilla explícitos. Estuvo la mayor parte del camino, pero no dio el último paso.

Estoy confundido de cómo funciona esto iy chambos son valores L.

Exactamente. Quiere valores l, que es algo que puede especificar en los argumentos de la plantilla:

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

o una forma que funciona en más casos:

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

Un poco de escritura adicional, pero necesaria si la deducción del argumento falla por alguna razón.