Home > database >  How does std::map resolve insert() overload between const lvalue reference and rvalue reference
How does std::map resolve insert() overload between const lvalue reference and rvalue reference

Time:01-26

I am writing a template library that is supposed to mirror std::map's interface. I stumbled across a question when implementing the following insert() overloads.

iterator insert( const value_type& value );
template< class P > iterator insert( P&& value );

cppreference writes about the second overload: The overload is equivalent to emplace(std::forward<P>(value)) and only participates in overload resolution if std::is_constructible<value_type, P&&>::value == true.

Given this, I am wondering for which possible arguments std::is_constructible will ever be false? I have experimented a bit with possible types but everything I have tried so far fulfils the requirement.

std::map<std::string,int> map;
std::cout
<< ((std::is_constructible<std::map<std::string,int>::value_type, const std::pair<const std::string,int>&&>::value)? "yes" : "no")
<< ((std::is_constructible<std::map<std::string,int>::value_type, const std::pair<std::string,int>&&>::value)? "yes" : "no")
<< ((std::is_constructible<std::map<std::string,int>::value_type, std::pair<const std::string,int>&&>::value)? "yes" : "no")
<< ((std::is_constructible<std::map<std::string,int>::value_type, std::pair<std::string,int>&&>::value)? "yes" : "no")
<< std::endl;

Output:

yesyesyesyes

In other words, how can I specifically call the first overload over the second?

Possibly related questions:

CodePudding user response:

You aren't doing overload resolution on const lvalue ref vs rvalue ref, you are doing overload resolution on const lvalue ref to concrete type vs rvalue ref to template parameter.

This means the first overload is a better match whenever you are passing cvref value_type, and the second is a better match otherwise. (Neither match when you pass something unrelated)

  • Related