fiz
fiz

Reputation: 936

Best Way to Create N Objects at Compile Time

I wondered how you would go about creating N objects at compile time with templates. Or this was indeed even good practise.

I have a header file containing some constants:

constexpr size_t N_TIMES = 3;
constexpr uint32_t MIN[N_TIMES] = {0,1,2};
constexpr uint32_t MAX[N_TIMES] = {1,2,3};

Then a header file containing a template which will be generate "N" times:

template <typename T>
class foo
{

public:

  foo(uint32_t min , uint32_t max) :
    min(min),
    max(max)
  {
    std::cout << "I was created with " << min << " " << max << std::endl;
  }

private:

  const uint32_t min;
  const uint32_t max;
};

The part I'm a little unsure about is I have:

template <typename T>

class bar 
{
public:

  bar()
  {

    for(auto i = 0; i < N_TIMES; i ++)
          {
            foo_[i] = foo<T>(MIN[i], MAX[i]);
          }
  }
private:
  std::array<foo<T>, N_TIMES> foo_;
};

I currently get the error:

cannot be assigned because its copy assignment operator is implicitly deleted

But since it's in the constructor, it'll generate this after compiling anyway. So really I was just wondering how I should be going about this instead. If there was some kind of clever recursive trick I could pull to create these objects for me at compile time.

Upvotes: 1

Views: 183

Answers (1)

Jarod42
Jarod42

Reputation: 217293

You may use std::index_sequence:

namespace detail
{

    template <typename T, std::size_t N, std::size_t...Is>
    std::array<Foo<T>, N> make_foo_array(std::index_sequence<Is...>)
    {
        return {{Foo<T>(MIN[Is], MAX[Is])...}};    
    }

}

template <typename T, std::size_t N>
std::array<Foo<T>, N> make_foo_array()
{
    return detail::make_foo_array<T, N>(std::make_index_sequence<N>{});
}

And then

template <typename T>
class bar 
{
public:
    bar() : foo_(make_foo_array<T, N_TIMES>()) {}
private:
    std::array<foo<T>, N_TIMES> foo_;
};

Upvotes: 1

Related Questions