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