Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why doesn't make_pair<string, string>() call the copy contructor, when given const string&?

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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));

>Solution :

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading