std::map 如何解决常量左值引用和右值引用之间的 insert() 重载

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

提问人:chiasmos 提问时间:1/26/2023 更新时间:1/26/2023 访问量:54

问:

我正在编写一个模板库,该模板库应该镜像 std::map 的接口。我在实现以下 insert() 重载时偶然发现了一个问题。

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

cppreference 写下第二个重载:重载等价于并且仅在 时参与重载解决。emplace(std::forward<P>(value))std::is_constructible<value_type, P&&>::value == true

鉴于此,我想知道哪些可能的论点是错误的?我已经尝试了一些可能的类型,但到目前为止我尝试的所有内容都满足了要求。std::is_constructible

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;

输出:

yesyesyesyes

换句话说,我怎样才能专门调用第一个重载而不是第二个重载?

可能相关的问题:

C++ 模板 std stdmap rvalue-reference

评论

0赞 BoP 1/26/2023
整理出完全错误的参数,例如 .否则绝对会匹配一切!还有另一个重载规则,它偏向于非模板而不是模板,这可以使第一个版本在完全匹配时有机会。is_constructiblecomplex<double>P&&
0赞 chiasmos 1/26/2023
我现在明白了。我很困惑,因为 cppreference 的措辞听起来像是第二个重载比第一个重载更受限制,而事实恰恰相反。

答:

2赞 Caleth 1/26/2023 #1

您不是在对常量左值引用与右值引用进行重载解析,而是对常量左值引用到具体类型与右值引用到模板参数进行重载解析。

这意味着每当您传递 cvref 时,第一个重载都是更好的匹配,否则第二个重载是更好的匹配。(当您传递不相关内容时,两者都不匹配)value_type

评论

0赞 chiasmos 1/26/2023
刚刚用我自己的实现测试了它,这是完全正确的,我可以重现这种行为。非常感谢!