1

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:

chiasmos
  • 110
  • 7
  • The `is_constructible` sorts out totally wrong parameters, like `complex`. Otherwise `P&&` would match absolutely everything! There is another overload rule that favors non-templates over templates, which can give the first version a chance when it matches exactly. – BoP Jan 26 '23 at 10:41
  • I understand now. I was confused because the wording on cppreference made it sound like the second overload is more restricted that the first, when it's the opposite. – chiasmos Jan 26 '23 at 10:57

1 Answers1

2

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)

Caleth
  • 52,200
  • 2
  • 44
  • 75
  • Just tested it with my own implementation and that's exactly right, I can reproduce this behaviour. Many thanks! – chiasmos Jan 26 '23 at 10:55