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
CodePudding user response:
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.
CodePudding user response:
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.