C++11环境下基于模板参数大小的列表数组实现开哈希表:统一初始化所有列表分配器的方法问询
Since you're stuck with C++11 and can't use std::vector due to allocator nesting issues, here are two practical, compliant approaches to get all your std::list instances using the same allocator:
Approach 1: Post-Construction Swap (Simplest & Most Readable)
Instead of fighting to initialize the array directly with the allocator, you can default-construct each list first, then swap each one with a temporary list built using your target allocator. This works because std::list's swap propagates the allocator (for standard allocators like std::allocator, propagate_on_container_swap is set to true_type).
Here's the modified class code:
#include <list> #include <utility> // For std::swap template<typename KEY, typename VAL, typename ALLOC=std::allocator<struct _internal>, size_t TBL_SIZE=100> class open_hash_table{ private: // Properly define your internal struct first struct _internal { KEY key; VAL value; // Add any required constructors or members here }; std::list<_internal, ALLOC> _table[TBL_SIZE]; public: open_hash_table(ALLOC allocator=ALLOC()) { // Iterate over every list in the array for (auto& lst : _table) { // Create a temporary list with your desired allocator std::list<_internal, ALLOC> temp_list(allocator); // Swap to replace the default-constructed list's allocator lst.swap(temp_list); } } // Add your hash table core methods here... };
Key Notes:
- This avoids complex template trickery and is easy to maintain.
- If you're using a custom allocator, ensure it has
propagate_on_container_swapset totrue(standard allocators likestd::allocatoralready do this).
Approach 2: Template Metaprogramming for Aggregate Initialization
If you want to initialize all lists directly in the constructor initializer list (no post-construction steps), you can implement a basic index sequence (since std::index_sequence is C++14-only) to generate an initializer list with TBL_SIZE copies of your allocator.
First, add this C++11-compatible index sequence implementation:
// Custom index sequence for C++11 template <std::size_t... Is> struct index_sequence {}; template <std::size_t N, std::size_t... Is> struct make_index_sequence : make_index_sequence<N-1, N-1, Is...> {}; template <std::size_t... Is> struct make_index_sequence<0, Is...> : index_sequence<Is...> {};
Then update your hash table class:
#include <list> // Include the index_sequence implementation above here... template<typename KEY, typename VAL, typename ALLOC=std::allocator<struct _internal>, size_t TBL_SIZE=100> class open_hash_table{ private: struct _internal { KEY key; VAL value; }; std::list<_internal, ALLOC> _table[TBL_SIZE]; // Helper to generate the initializer list template <std::size_t... Is> static std::initializer_list<std::list<_internal, ALLOC>> make_list_init(const ALLOC& alloc, index_sequence<Is...>) { // Comma expression ignores the index, constructs a list with alloc each time return { (Is, std::list<_internal, ALLOC>(alloc))... }; } public: open_hash_table(ALLOC allocator=ALLOC()) : _table(make_list_init(allocator, make_index_sequence<TBL_SIZE>{})) {} // Add your hash table methods here... };
Key Notes:
- This initializes all lists directly with your target allocator during construction, skipping default-constructed lists entirely.
- The comma expression
(Is, std::list<...>(alloc))ensures each element in the initializer list uses your allocator, ignoring the index value from the sequence.
Both methods are fully C++11-compliant and solve your problem of sharing a single allocator across all lists in the template-sized array.
内容的提问来源于stack exchange,提问作者MrHarmz

