In std::make_pair
there is only one implementation C++14 onwards
template< class T1, class T2 > constexpr std::pair<V1,V2> make_pair( T1&& t, T2&& u );
Both parameters are R-value references and according to this
R-values references cannot be initialized with l-values.
int i = 1;
char ch = 'a';
std::unordered_map<int, char> mp;
mp.insert(make_pair<int,char>(i, ch));
So when I try to use make_pair as in the above code it correctly throws an error error: cannot bind rvalue reference of type 'int&&' to lvalue of type 'int'
.
However it works perfectly for the above code if I change drop the template arguments and call it as
mp.insert(make_pair(i, ch));
I'm confused how this works as i
and ch
both are L-values. Does template argument resolution convert L-values to R-values or like how does this work?
The parameters of make_pair
are not declared as rvalue-reference, but forwarding reference.
Forwarding references are a special kind of references that preserve the value category of a function argument, making it possible to forward it by means of std::forward. Forwarding references are either:
- function parameter of a function template declared as rvalue reference to cv-unqualified type template parameter of that same function template:
Forwarding referece works with both lvalues and rvalues, with the help of template argument deduction. When being passed an lvalue, the template parameter would be deduced as lvalue-reference, after reference collapsing, the function parameter is lvalue-reference too. When being passing an rvalue, the template parameter would be deduced as non-reference, the function parameter is rvalue-reference.
On the other hand, if you specify the template argument explicitly like make_pair<int,char>(...)
, the function parameter become rvalue-reference accordingly.