1

Consider this simple example of having a map type as a member of a class where the value type of the map is the enclosing class:

#include <map>
#include <unordered_map>

// compiles
class trie {
    std::map<char, trie> data_;
};

// fails to compile on GCC, Clang, works on MSVC
class trie2 {
    std::unordered_map<char, trie2> data_;
};

When the map type is std::map, this seems to compile fine everywhere. For Clang and GCC, on all versions I've tried that support C++17 up to the latest (Clang 11, GCC 10.2), using std::unordered_map fails to compile with some variation of:

In file included from /opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/bits/stl_algobase.h:64,
                 from /opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/bits/stl_tree.h:63,
                 from /opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/map:60,
                 from <source>:1:
/opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/bits/stl_pair.h: In instantiation of 'struct std::pair<const char, trie2>':
/opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/ext/aligned_buffer.h:91:28:   required from 'struct __gnu_cxx::__aligned_buffer<std::pair<const char, trie2> >'
/opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/bits/hashtable_policy.h:233:43:   required from 'struct std::__detail::_Hash_node_value_base<std::pair<const char, trie2> >'
/opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/bits/hashtable_policy.h:279:12:   required from 'struct std::__detail::_Hash_node<std::pair<const char, trie2>, false>'
/opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/bits/hashtable_policy.h:1973:13:   required from 'struct std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<const char, trie2>, false> > >'
/opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/bits/hashtable.h:173:11:   required from 'class std::_Hashtable<char, std::pair<const char, trie2>, std::allocator<std::pair<const char, trie2> >, std::__detail::_Select1st, std::equal_to<char>, std::hash<char>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >'
/opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/bits/unordered_map.h:105:18:   required from 'class std::unordered_map<char, trie2>'
<source>:11:37:   required from here
/opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/bits/stl_pair.h:218:11: error: 'std::pair<_T1, _T2>::second' has incomplete type
  218 |       _T2 second;                ///< The second member
      |           ^~~~~~
<source>:10:7: note: forward declaration of 'class trie2'
   10 | class trie2 {
      |       ^~~~~
Compiler returned: 1

MSVC compiles this example with std::unordered_map. Is this a bug in the standard library implementations for GCC/Clang or is there some reason according to the standard that this should not be expected to work?

Jake Cobb
  • 1,811
  • 14
  • 27

0 Answers0