Both GCC and Clang refuse to compile this one:
#include <string>
#include <utility>
using namespace std;
int main() {
const string s = "12345";
const string& r = s;
auto p = std::make_pair<string, string>(r, r);
}
GCC says:
error: cannot bind rvalue reference of type ‘std::__cxx11::basic_string<char>&&’ to lvalue of type ‘const std::string’ {aka ‘const std::__cxx11::basic_string<char>’}
While Clang says:
error: no matching function for call to 'make_pair'
Since I'm giving make_pair
explicit types, why doesn't it construct new strings from const string&
?
This one compiles:
auto p = std::make_pair<string, string>(string(r), string(r));
Assuming C++11 or later:
std::make_pair
is not supposed to be used with explicitly-specified template arguments. They are intended to be deduced from the function arguments via forwarding references. The signature of std::make_pair
is
template<class T1, class T2>
constexpr std::pair<V1, V2> make_pair(T1&& t, T2&& u);
This shows that T1
and T2
are used as forwarding references and therefore shouldn't be specified explicitly. (V1
/V2
are computed from T1
/T2
by decay.)
Explicitly specifying the template arguments breaks the forwarding behavior. With string
as template argument you get string&&
in the function parameter, which is a rvalue reference that doesn't accept lvalues. You would need to provide const string&
as template argument for T
to make T&&
also const string&
.
But don't do that and just write
auto p = std::make_pair(r, r);
as is intended usage.
Before C++11 there were no forwarding references and std::make_pair
looked like this:
template <class T1, class T2>
std::pair<T1, T2> make_pair(T1 t, T2 u);
So the code from your question would compile prior to C++11. Still, specifying the template arguments was redundant then as well.