1

I have to initialize a std::array<my_vector, N>, my_vector being a std::vector with a custom allocator. The way I did it is:

  1. Allocated N memory pools
  2. Created a std::array of allocator, that each have their memory pool
  3. Created a std::array of std::vector, that each have their allocator.

The simplified code looks like this:

std::array<std::array<char, POOL_SIZE>, N> memory_pools;

std::array<allocator<POOL_SIZE>, N> allocators{
    std::get<0>(memory_pools),
    std::get<1>(memory_pools),
    std::get<2>(memory_pools),
    //...
    std::get<N-1>(memory_pools),
};

using my_vector = std::vector<my_class, my_allocator>;

std::array<my_vector, N> vectors{
    my_vector{std::get<0>(allocators)},
    my_vector{std::get<1>(allocators)},
    my_vector{std::get<2>(allocators)},
    //...
    my_vector{std::get<N-1>(allocators)},
}

This works, however, this is quite verbose, given that my constant N is over 100, and writing all this by hand produces bloated code, and when I change N, I have to write this whole section again.

Question: Is there any way to make the compiler write the initialisation for me ?

What I want to do is

std::array<allocator<POOL_SIZE>, N> allocators =
make_array_from_pool<POOL_SIZE, N>(memory_pools);

std::array<my_vector, N> vectors = 
make_array_from_allocators<N>(allocators);

I've already tried to do some recursive templated function, inside a nested class, but I'm confronted with conversion error.

This is roughly what I was trying:


template<size_t POOL_SIZE, size_t N, size_t ORDER> 
class ArrayMaker{
    static std::array<allocator<POOL_SIZE>, ORDER> from_pool(
    std::array<std::array<char, POOL_SIZE>, N>
    memory_pool
){
    return {
        ArrayMaker<POOL_SIZE, N, ORDER-1>::from_pool(memory_pool),
        std::get<ORDER-1>(memory_pool)
    };
}
};

template<size_t POOL_SIZE, size_t N> 
class ArrayMaker<POOL_SIZE, N, 1>{
    static std::array<allocator<POOL_SIZE>, 1> from_pool(
    std::array<std::array<char, POOL_SIZE>, N>
    memory_pool
){
    return {std::get<0>(memory_pool)};
}
};

template<size_t POOL_SIZE, size_t N> 
static std::array<allocator<POOL_SIZE>, N> make_array_from_pool(
    std::array<std::array<char, POOL_SIZE>, N>
    memory_pool
){
    return ArrayMaker<POOL_SIZE,N, N>::from_pool(memory_pool);
}

The error I get is could not convert ... from '<brace-enclosed initializer list>' to 'std::array<allocator<POOL_SIZE>, 2>'

It's my understanding that it is because std::array only supports aggregate initialisation.

1
  • Any restrictions on C++ version? Commented Sep 6, 2019 at 16:02

1 Answer 1

1

You don't need any recursion to achieve this, you can simply use std::index_sequence. E.g.

template <std::size_t... Is>
void init_arrays_impl(std::index_sequence<Is...>)
{
    static constexpr auto N = sizeof...(Is);

    std::array<std::array<char, POOL_SIZE>, N> memory_pools;

    std::array<allocator<POOL_SIZE>, N> allocators{
        std::get<Is>(memory_pools)...
    };

    using my_vector = std::vector<my_class, my_allocator>;

    std::array<my_vector, N> vectors{
        my_vector{std::get<Is>(allocators)}...
    };
}

template <std::size_t N>
void init_arrays()
{
    init_arrays_impl(std::make_index_sequence<N>{});
}

live example on godbolt.org

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

2 Comments

Wow, that is super clean. Thank you, I'll try that ! Quick question: in this demo, I guess the std::array would fall out of scope as soon as init_arrays_impl completes. What would be the recommended way to proceed for class member std::array ? Create functions that return std::array and hope copy-elision will work its magic, or pass my allocators and vectors variables as parameters to init_arrays_impl ?
@NebularNoise: use a function that returns an array. RVO will very likely take place. In C++17 copy elision is mandatory.

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.