从std::map派生的类不在Visual C++上编译(但在gcc和clang上编译)



我正在编写一些封装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_typepair<K,V>的typedef。这解释了VC++错误消息。

解决方法:自己在map2中消除参数名称的歧义。

最新更新