Class 派生自 std::map 不在 Visual C++ 上编译(但在 gcc 和 clang 上编译)

Class derived from std::map does not compile on Visual C++ (but compiles on gcc and clang)

我正在编写一些包装 std::map 的容器 class。简化版如果是:

#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++ 而不是 在做什么,那就是 two-phase 名称查找。由于名称查找只有一个阶段,因此必须在该阶段查找 value_type。作为 hack,VC++ 然后已经在此处查看依赖基 类,例如 std::map<key_type, value_type>

这错误地找到了 std::map<K, V>::value_typepair<K,V> 的类型定义。这解释了 VC++ 错误消息。

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