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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从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中的参数名称的歧义。

以上是关于从std :: map派生的类不能在Visual C ++上编译(但在gcc和clang上编译)的主要内容,如果未能解决你的问题,请参考以下文章

C++:当包含从类模板派生的类的标头时,编译器警告 C4505

为从 std::vector 派生的类正确重载双等号

派生自std :: exception的类的赋值运算符

visual studio 2017 STL 可视化器因一个 std::map<MyIntrusivePtr, std::tuple<....>> 失败

“在没有模板参数的情况下使用的类 std::map”错误

使用 Visual Studio 2010 继承 Windows 窗体类