C++17中std::unordered_map的推导指南

7

我阅读了关于C++17中std::unordered_map的类型推导指南,来源是cppreference

接着,我尝试运行以下示例,它是从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
           ^~~~~~~~~~~~~

为什么编译器会报错?

3
永远不要在 map 中使用 char* 作为键。 - user2672107
3
除非你真的知道你在做什么。 - Deduplicator
7
libstdc++目前还没有为其无序关联容器实现模板参数推导指南。(而这些容器恰好是以一种防止隐式推导工作的方式实现的。) - T.C.
3
@manni66 的推导指南可以轻松地将字符指针更改为 std::string 类型... - W.F.
1个回答

2
编辑:在与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 m2{std::pair{"foo", 2}, {"bar", 3}};

这实际上与以下相同:
// not const char*const, but rather const char*
std::unordered_map m2{std::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*类型。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接