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

时间:2017-09-16 08:48:12

标签: c++ g++ c++17 unordered-map template-deduction

我已经阅读了使用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
           ^~~~~~~~~~~~~

为什么编译器会出错?

1 个答案:

答案 0 :(得分:2)

edit:与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模板参数,而无需显式地编写它们,这是毫无用处的。

此问题在Issue 3025: Map-like container deduction guides should use pair<Key, T>, not pair<const Key, T>的图书馆工作组(LWG)页面上提到。 GCC只是决定使用不符合标准的推论指南,该指南使此功能有用,而不是坚持遵循符合标准的有用性指南。

此问题很可能很快就会有正式的DR,使GCC的实施符合修订后的标准。

注意:您可以在GCC bug report中阅读有关此问题的详细信息,以了解更多信息。

P.S。希望您知道自己在做什么,键入const char*类型的密钥。