【问题标题】:Class derived from std::map does not compile on Visual C++ (but compiles on gcc and clang)从 std::map 派生的类不能在 Visual C++ 上编译(但在 gcc 和 clang 上编译)
【发布时间】:2018-08-09 13:18:13
【问题描述】:

我正在编写一些包装 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&lt;key_type, value_type&gt; 类型而不是 value_type。但是为什么这样做,而 gcc 和 clang 接受我的代码就好了?

【问题讨论】:

  • 我不知道为什么 VC++ 会这样做(尽管那个编译器的名称查找规则一直很奇怪),但简单的解决方案是不要将你的模板参数命名为与 base 中的 typedefs 相同类。
  • 仅供参考:这篇文章地址继承自std::vector,但我认为其中大部分也适用于std::mapstackoverflow.com/questions/4353203/…
  • 通过设置/permissive- 命令行开关修复此问题
  • @Mgetz 如果您可以控制构建环境,这是一个选项。但是对于 CI 构建,您通常会使用其他人设置的编译器标志,并且需要调整您的代码以使用这些标志进行编译。所以设置命令行开关并不是解决这个问题的通用方法。
  • @Dreamer 是的,我建议说服他们使用/permissive-,因为它有助于强制遵守标准。

标签: c++ templates inheritance stdmap


【解决方案1】:

问题很可能是 Visual C++ 没有在做的事情,那就是两阶段名称查找。由于名称查找只有一个阶段,因此必须在该阶段查找value_type。作为一个 hack,VC++ 已经查看了依赖的基类,比如这里的std::map&lt;key_type, value_type&gt;

这会错误地找到std::map&lt;K, V&gt;::value_type,这是pair&lt;K,V&gt; 的类型定义。这解释了 VC++ 错误消息。

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

【讨论】:

  • 同意——这听起来很合理。建议使用完全不同的名称。无论如何,这可能是个好主意
  • 如果是这种情况,那么 VS2017 应该可能在 /permissive- 和 C++17 模式下编译此代码,因为据称这应该支持两阶段。编辑Confirmed
猜你喜欢
  • 2019-06-06
  • 2015-09-22
  • 1970-01-01
  • 2020-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-03
相关资源
最近更新 更多