I am new to allocators. I am experimenting with a custom allocator used to allocate std::unordered_map and string:
#include <string>
#include <string_view>
#include <unordered_map>
template < typename T >
struct MyMem
{
typedef T value_type;
T * allocate (std::size_t size)
{
return new T [size];
}
void deallocate ( T * t, std::size_t size ) noexcept
{
delete [] t;
}
};
using lstr = std::basic_string<
char,
std::char_traits<char>,
MyMem<char>
>;
struct lstrHash
{
std::size_t operator()(const lstr & x) const
{
std::string_view sv(&x[0], x.size());
return std::hash<decltype(sv)>()(sv);
}
};
struct lstrEqual
{
bool operator()(const lstr & x, const lstr & y) const
{
if (x.size() != y.size()) return false;
for (auto xi = x.begin(), yi = y.begin(); xi != x.end(); ++xi, ++yi)
{
if ( *xi != *yi ) return false;
}
return true;
}
};
template <typename Key, typename T,
typename Hash = std::hash<Key>,
typename KeyEqual = std::equal_to<Key> >
using unmap = std::unordered_map <
Key, T,
Hash,
KeyEqual,
MyMem<std::pair<const Key, T> > >;
int main()
{
unmap<lstr, int, lstrHash, lstrEqual> a;
unmap<lstr, int, lstrHash, lstrEqual> b(10);
}
However, the compiler produces the following error:
g++ -std=gnu++20 tests/soask.cpp -o soask
In file included from /home/i56087/opt/gcc-13/include/c++/13.2.1/bits/unordered_map.h:33,
from /home/i56087/opt/gcc-13/include/c++/13.2.1/unordered_map:41,
from tests/soask.cpp:3:
/home/i56087/opt/gcc-13/include/c++/13.2.1/bits/hashtable.h: In instantiation of ‘std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::_Hashtable(const _Hash&, const _Equal&, const allocator_type&) [with _Key = std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >; _Value = std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int>; _Alloc = MyMem<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int> >; _ExtractKey = std::__detail::_Select1st; _Equal = lstrEqual; _Hash = lstrHash; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, false, true>; allocator_type = MyMem<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int> >]’:
/home/i56087/opt/gcc-13/include/c++/13.2.1/bits/hashtable.h:1193:32: required from ‘std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::_Hashtable(size_type, const _Hash&, const _Equal&, const allocator_type&) [with _Key = std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >; _Value = std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int>; _Alloc = MyMem<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int> >; _ExtractKey = std::__detail::_Select1st; _Equal = lstrEqual; _Hash = lstrHash; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, false, true>; size_type = long unsigned int; allocator_type = MyMem<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int> >]’
/home/i56087/opt/gcc-13/include/c++/13.2.1/bits/unordered_map.h:162:9: required from ‘std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map(size_type, const hasher&, const key_equal&, const allocator_type&) [with _Key = std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >; _Tp = int; _Hash = lstrHash; _Pred = lstrEqual; _Alloc = MyMem<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int> >; size_type = long unsigned int; hasher = lstrHash; key_equal = lstrEqual; allocator_type = MyMem<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int> >]’
tests/soask.cpp:66:45: required from here
/home/i56087/opt/gcc-13/include/c++/13.2.1/bits/hashtable.h:489:27: error: too many initializers for ‘std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int>, MyMem<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int> >, std::__detail::_Select1st, lstrEqual, lstrHash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::__node_alloc_type’
489 | __hashtable_alloc(__node_alloc_type(__a)),
| ^~~~~~~~~~~~~~~~~~~~~~
In file included from /home/i56087/opt/gcc-13/include/c++/13.2.1/bits/hashtable.h:35:
/home/i56087/opt/gcc-13/include/c++/13.2.1/bits/hashtable_policy.h: In instantiation of ‘void std::__detail::_Hashtable_alloc<_NodeAlloc>::_M_deallocate_buckets(__buckets_ptr, std::size_t) [with _NodeAlloc = MyMem<std::__detail::_Hash_node<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int>, true> >; __buckets_ptr = std::__detail::_Hashtable_alloc<MyMem<std::__detail::_Hash_node<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int>, true> > >::__node_base**; std::size_t = long unsigned int]’:
/home/i56087/opt/gcc-13/include/c++/13.2.1/bits/hashtable.h:451:42: required from ‘void std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::_M_deallocate_buckets(__buckets_ptr, size_type) [with _Key = std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >; _Value = std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int>; _Alloc = MyMem<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int> >; _ExtractKey = std::__detail::_Select1st; _Equal = lstrEqual; _Hash = lstrHash; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, false, true>; __buckets_ptr = std::__detail::_Hashtable_alloc<MyMem<std::__detail::_Hash_node<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int>, true> > >::__node_base**; size_type = long unsigned int]’
/home/i56087/opt/gcc-13/include/c++/13.2.1/bits/hashtable.h:456:30: required from ‘void std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::_M_deallocate_buckets() [with _Key = std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >; _Value = std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int>; _Alloc = MyMem<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int> >; _ExtractKey = std::__detail::_Select1st; _Equal = lstrEqual; _Hash = lstrHash; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, false, true>]’
/home/i56087/opt/gcc-13/include/c++/13.2.1/bits/hashtable.h:1609:28: required from ‘std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::~_Hashtable() [with _Key = std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >; _Value = std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int>; _Alloc = MyMem<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int> >; _ExtractKey = std::__detail::_Select1st; _Equal = lstrEqual; _Hash = lstrHash; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, false, true>]’
/home/i56087/opt/gcc-13/include/c++/13.2.1/bits/unordered_map.h:148:7: required from here
/home/i56087/opt/gcc-13/include/c++/13.2.1/bits/hashtable_policy.h:2058:28: error: too many initializers for ‘MyMem<std::__detail::_Hash_node_base*>’
2058 | __buckets_alloc_type __alloc(_M_node_allocator());
| ^~~~~~~
/home/i56087/opt/gcc-13/include/c++/13.2.1/bits/hashtable_policy.h: In instantiation of ‘std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_base** std::__detail::_Hashtable_alloc<_NodeAlloc>::_M_allocate_buckets(std::size_t) [with _NodeAlloc = MyMem<std::__detail::_Hash_node<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int>, true> >; __buckets_ptr = std::__detail::_Hashtable_alloc<MyMem<std::__detail::_Hash_node<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int>, true> > >::__node_base**; std::size_t = long unsigned int]’:
/home/i56087/opt/gcc-13/include/c++/13.2.1/bits/hashtable.h:442:47: required from ‘std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::__buckets_ptr std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::_M_allocate_buckets(size_type) [with _Key = std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >; _Value = std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int>; _Alloc = MyMem<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int> >; _ExtractKey = std::__detail::_Select1st; _Equal = lstrEqual; _Hash = lstrHash; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, false, true>; __buckets_ptr = std::__detail::_Hashtable_alloc<MyMem<std::__detail::_Hash_node<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int>, true> > >::__node_base**; size_type = long unsigned int]’
/home/i56087/opt/gcc-13/include/c++/13.2.1/bits/hashtable.h:1198:17: required from ‘std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::_Hashtable(size_type, const _Hash&, const _Equal&, const allocator_type&) [with _Key = std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >; _Value = std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int>; _Alloc = MyMem<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int> >; _ExtractKey = std::__detail::_Select1st; _Equal = lstrEqual; _Hash = lstrHash; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, false, true>; size_type = long unsigned int; allocator_type = MyMem<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int> >]’
/home/i56087/opt/gcc-13/include/c++/13.2.1/bits/unordered_map.h:162:9: required from ‘std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map(size_type, const hasher&, const key_equal&, const allocator_type&) [with _Key = std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >; _Tp = int; _Hash = lstrHash; _Pred = lstrEqual; _Alloc = MyMem<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int> >; size_type = long unsigned int; hasher = lstrHash; key_equal = lstrEqual; allocator_type = MyMem<std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, MyMem<char> >, int> >]’
tests/soask.cpp:66:45: required from here
/home/i56087/opt/gcc-13/include/c++/13.2.1/bits/hashtable_policy.h:2042:28: error: too many initializers for ‘MyMem<std::__detail::_Hash_node_base*>’
2042 | __buckets_alloc_type __alloc(_M_node_allocator());
| ^~~~~~~
It seems my allocator has some missing definitions, but the compiler error message is too hard for me to decipher. ChatGPT also says the error may be due to the fact that the allocator is incompatible with the stl container. How to correctly structure my allocator to make it work?
Thanks!
deallocateto avoid the warning spam for the unused parameter. It is surprisingly verbose.