我正在编写一些封装std::map的容器类。简化版本,如果是:
#include <map>
template <typename key_type, typename value_type>
class map2 : private std::map<key_type, value_type>
{
public:
void update(const key_type& key, value_type value)
{
(*this)[key] = std::move(value);
}
};
int main()
{
map2<int, int> m;
m.update(1,4);
}
这段代码在gcc和clang上编译得很好,但在Visual C++上(我测试了2015版本以及在http://rextester.com/l/cpp_online_compiler_visual)失败:
source_file.cpp(16): error C2664: 'void map2<int,int>::update(const int &,std::pair<const _Kty,_Ty>)': cannot convert argument 2 from 'int' to 'std::pair<const _Kty,_Ty>'
with
[
_Kty=int,
_Ty=int
]
source_file.cpp(16): note: No constructor could take the source type, or constructor overload resolution was ambiguous
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23506 for x64
因此,Visual C++以某种方式假设map2::update()的value
参数的类型是std::pair<key_type, value_type>
,而不是value_type
。但是,为什么它这样做,而gcc和clang接受我的代码很好?
问题可能是Visual C++没有在做什么,这是两阶段的名称查找。由于名称查找只有一个阶段,因此必须在该阶段查找value_type
。作为一个破解,VC++已经在这里研究了依赖基类,比如std::map<key_type, value_type>
。
这错误地找到了std::map<K, V>::value_type
,pair<K,V>
的typedef。这解释了VC++错误消息。
解决方法:自己在map2
中消除参数名称的歧义。