C++中std :: unordered_map的演绎指南17

msc*_*msc 7 c++ unordered-map g++ template-argument-deduction c++17

我已经阅读了有关std::unordered_map使用cppreference的 C++ 17中的演绎指南.

然后尝试运行以下示例,该示例是从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
}
Run Code Online (Sandbox Code Playgroud)

但是,编译器会出错.

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
           ^~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

为什么编译器会出错?

Mic*_*ler 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
Run Code Online (Sandbox Code Playgroud)

也是如此

std::unordered_map m2{
std::pair<char const* const, int>{"foo", 2}, {"bar", 3}}; // guide #2
Run Code Online (Sandbox Code Playgroud)

但 GCC 偏离了标准并允许:

std::unordered_map m2{std::pair{"foo", 2}, {"bar", 3}};
Run Code Online (Sandbox Code Playgroud)

这实际上与

// not const char*const, but rather const char*
std::unordered_map m2{std::pair<const char*, int>{"foo", 2}, {"bar", 3}};
Run Code Online (Sandbox Code Playgroud)

这不符合标准,因为该对的关键部分应该是 const。这实际上比标准更好,因为这种偏差使得可以推断出模板参数。这与标准指南形成鲜明对比,使得std::unordered_map在不明确编写模板参数的情况下无法推断出模板参数,这是非常无用的。

图书馆工作组 (LWG) 页面第 3025 期提到了此问题:类地图容器推导指南应使用pair<Key, T>,而不是pair<const Key, T>。GCC 只是决定使用不合格的推导指南,这使得该功能变得有用,而不是坚持使用有用的符合标准的指南。

最有可能的是,这个问题很快就会有正式的 DR,使 GCC 的实现符合修订后的标准。

注意:您可以阅读GCC 错误报告中有关此问题的详细信息,了解更多详细信息。

PS 我希望你知道你在做什么,制作 type 的 key const char*