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:
- Preventing non-const lvalues from resolving to rvalue reference instead of const lvalue reference
- Overload resolution between const lvalue reference and rvalue reference
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)