2

I want to create an open hash table. And i want to use an array of lists, where the size of the array is a template parameter, but the problem is i don't know how to pass an allocator to all of the list instances, and i cannot use vector, because i will need another allocator for list allocation (alloception), is there a way to initialize a whole array of lists with the same value? I know i can initialize like this list<int> mylist[] = {{allocator}, {allocator}, {allocator}}

But the idea is to have size as a template variable. Example:

template<typename KEY, typename VAL, typename ALLOC=std::allocator<struct _internal>, size_t TBL_SIZE=100>
class open_hash_table{
private: 
   std::list<struct _internal, ALLOC=ALLOC> _table[TBL_SIZE];
public: 
    open_hash_table(ALLOC allocator=ALLOC())
    :_table({allocator, allocator ... allocator}){}
};

P.s. my compiler supports upto c++11

4
  • Since the table size is rather large (100), I think a loop is better than aggregate initialization. Commented Mar 9, 2022 at 14:45
  • If you can afford it, the easiest way would be to just default construct elements and then std::fill() (or .fill() for std::array) it with elements constructed with allocators. Otherwise, you'd probably need to wrap std::list with some class that will default-construct list with your allocator. Commented Mar 9, 2022 at 14:47
  • You can create storage array for lists, and then initialize all the lists there using placement new. Commented Mar 9, 2022 at 14:51
  • You can create a initializer list recursively with vardiac templates. It's really ugly. My suggesti9on would be to get a newer compiler. This is so much simpler with more modern c++. Commented Mar 9, 2022 at 18:05

2 Answers 2

2

This uses C++14 for std::make_index_sequence and the std::index_sequence it produces but you can make your own implementation as shown here. Using a delegating constructor you can add another constructor that takes an index_sequence so you can then expand the sequence and get a variadic list of values like

template<typename KEY, typename VAL, typename ALLOC=std::allocator<struct _internal>, size_t TBL_SIZE=100>
class open_hash_table{
private: 
    std::list<struct _internal, ALLOC> _table[TBL_SIZE];
    template <std::size_t... Is>
    open_hash_table(ALLOC allocator, std::index_sequence<Is...>) 
    : _table{ std::list<struct _internal, ALLOC>{((void)Is, allocator)}... } {}
public: 
    open_hash_table(ALLOC allocator=ALLOC())
    : open_hash_table(allocator, std::make_index_sequence<TBL_SIZE>{}) {}
};

Your public constructor will call the private helper constructor and pass along an index_sequence that will have TBL_SIZE number of elements in it. Then in the delegating constructor the ((void)Is, allocator) part uses the comma operator to use each element of the index_sequence but we discard that in instead let the expression resolve to allocator. The (void)Is part casts the result of Is to void to suppress that it is unused. We have to use std::list<struct _internal, ALLOC>{ ... } as well because the constructor that takes an allocator is explicit so the type needs to be specified, no implicit conversion allowed.

Sign up to request clarification or add additional context in comments.

Comments

0

It is possible to initialize _table directly in member initializer lists through some metaprogramming techniques, but since TBL_SIZE's default value is 100, this will make the compile-time overhead slightly larger. It is more appropriate to just default construct _table and initializes its value in the constructor body.

And since TBL_SIZE is a compile-time constant, instead of using a raw array, you can just use std::array:

template<typename KEY, typename VAL, typename ALLOC=std::allocator<_internal>, size_t TBL_SIZE=100>
class open_hash_table{
private:
  std::array<std::list<_internal, ALLOC>, TBL_SIZE> _table;
public:
  open_hash_table(ALLOC allocator=ALLOC()) {
    _table.fill(std::list<_internal, ALLOC>(allocator));
  }
};

Also since this is C++, the struct keyword in struct _internal is unnecessary.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.