Home > Mobile >  C initialize array class with default value
C initialize array class with default value

Time:03-10

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.

  • Related