C++17 中 std::unordered_map 的推导指南
Posted
技术标签:
【中文标题】C++17 中 std::unordered_map 的推导指南【英文标题】:Deduction guides for std::unordered_map in C++17 【发布时间】:2017-09-16 08:48:12 【问题描述】:我已经阅读了关于使用 cppreference 的 C++17 中 std::unordered_map
的推导指南。
然后尝试运行以下示例,该示例是从 cppreference 复制的。
#include <unordered_map>
int main()
// std::unordered_map m1 = "foo", 1, "bar", 2; // Error: braced-init-list has no type
// cannot deduce pair<const Key, T> from
// "foo", 1 or "bar", 2
std::unordered_map m1 = std::initializer_list<
std::pair<char const* const, int>>("foo", 2, "bar", 3); // guide #2
std::unordered_map m2(m1.begin(), m1.end()); // guide #1
但是,编译器给出了错误。
main.cpp: In function 'int main()':
main.cpp:7:84: error: class template argument deduction failed:
std::pair<char const* const, int>>("foo", 2, "bar", 3); // guide #2
^
main.cpp:7:84: error: no matching function for call to 'unordered_map(std::initializer_list<std::pair<const char* const, int> >)'
In file included from /usr/local/include/c++/7.2.0/unordered_map:48:0,
from main.cpp:1:
/usr/local/include/c++/7.2.0/bits/unordered_map.h:101:11: note: candidate: template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> unordered_map(std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>)-> std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>
class unordered_map
^~~~~~~~~~~~~
为什么编译器会报错?
【问题讨论】:
永远不要在地图中使用 char* 作为键。 @manni66: ...除非你真的知道你在做什么。 libstdc++ 尚未为其无序关联容器实现推导指南。 (而这些容器恰好是以阻止隐式指南工作的方式实现的。) @manni66 演绎指南可以轻松将字符指针更改为std::string
...
【参考方案1】:
编辑:在与 GCC C++ 库 (libstdc++) 的开发人员讨论该问题后,我正在更新此答案。编辑后的答案更详细、更合理、更有方向。
从技术上讲,这是 GCC 中的编译器错误,而 clang 坚持标准。您的代码中的第一个指南适用于 clang-6 -stdlib=libc++。
std::unordered_map m1 = std::initializer_list<
std::pair<char const* const, int>>("foo", 2, "bar", 3); // guide #2
也是这样
std::unordered_map m2
std::pair<char const* const, int>"foo", 2, "bar", 3; // guide #2
但 GCC 偏离标准,允许:
std::unordered_map m2std::pair"foo", 2, "bar", 3;
实际上是一样的
// not const char*const, but rather const char*
std::unordered_map m2std::pair<const char*, int>"foo", 2, "bar", 3;
这不符合标准,因为该对的关键部分应该是 const。这实际上比标准要好,因为这种偏差使得推导模板参数成为可能。这与标准指南相反,如果不显式编写它们,就无法推断出std::unordered_map
模板参数,这是非常没用的。
图书馆工作组 (LWG) 页面 Issue 3025: Map-like container deduction guides should use pair<Key, T>, not pair<const Key, T> 提到了此问题。 GCC 只是决定使用不符合标准的扣除指南,这使该功能变得有用,而不是坚持使用符合标准的有用指南。
这个问题很可能很快就会有正式的 DR,使 GCC 的实现符合修订后的标准。
注意:您可以阅读GCC bug report 中有关此问题的详细信息,了解更多详细信息。
附:我希望您知道自己在做什么,制作const char*
类型的密钥。
【讨论】:
以上是关于C++17 中 std::unordered_map 的推导指南的主要内容,如果未能解决你的问题,请参考以下文章
Visual Studio 中基于 For 循环的 C++17 广义范围