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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With