0

I'm looking for a way to populate an array with elements of values at compile time rather then run time. So what I'm looking for is something like this

#define numbar
Bar foo[] = {Bar(0),Bar(1)....Bar(numbar)}

Does c++ have any way to do this? Perhaps using macro's or something like that?

Thijser
  • 2,625
  • 1
  • 36
  • 71
  • That question is looking to exclude things like macros with which I'm fine and therefore it is probably related but not duplicate. – Thijser Oct 23 '14 at 09:09
  • Did you read the question? `Solutions must be in C++ (no script, no macros, no pp or code generator based solutions pls)` –  Oct 23 '14 at 09:13
  • Well, looks like he deleted the link. It's not a duplicate but I think the link is still relevant, so [here is the related question](http://stackoverflow.com/questions/2978259/programmatically-create-static-arrays-at-compile-time-in-c) – PeterT Oct 23 '14 at 09:15
  • To do that at compile time a necessary but not sufficient requirement is that the `Bar` constructor is `constexpr`. Are you aware of this? It rather limits the performance gain, and so this is likely a premature optimization. – Cheers and hth. - Alf Oct 23 '14 at 09:16
  • Take a look at "template meta programming" this , looks related. – Matthias Oct 23 '14 at 09:17

2 Answers2

5

Assuming c++14:

constexpr auto num_bars = 100;

class Bar {
    constexpr Bar(int i);
};

template <std::size_t ...I>
constexpr auto generate_bars_impl(std::index_sequence<I...>) {
    return {Bar(I)...};
}

template <std::size_t N, typename Indices = std::make_index_sequence<N>>
constexpr auto generate_bars() {
   return generate_bars_impl(Indices());
}

constexpr auto generated = generate_bars<num_bars>();

This will give you an std::initializer_list in C++14. C++11: You should implement index_sequence and I think that initializer_list has no constexpr constructor.

Germán Diago
  • 7,473
  • 1
  • 36
  • 59
3

I am not sure if this is clever enough, but in the case you could use boost preprocessor to create the code as described in you example:

#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/seq/enum.hpp>

#define INIT(z, n, initializer)(initializer(n))
#define INIT_ARRAY(N, INITIALIZER) {BOOST_PP_SEQ_ENUM(BOOST_PP_REPEAT(5, INIT, Bar))}

struct Bar
{
    constexpr Bar(int ii) : i(ii) {}
    int i;
};

Bar data[] = INIT_ARRAY(5, Bar);

In general you can solve a lot of repetitive problems this way, but you often makes the code more complex and it less obvious what happens. So you should do this only if you have a lot of such think. Of course you can also do some metaprogramming, which can lead to quite long compile times

CK1
  • 694
  • 6
  • 13
  • You need constexpr in Bar or it could be initialized at runtime, not compile-time, with all threading issues that go associated with it. This solution requires boost. My solution below requires only core C++14, so depending on what can be afforded both would be valid. – Germán Diago Oct 23 '14 at 09:33
  • I would improve this solution adding static before Bar if in the context you use it you can, because static is thread-safe in C++11. – Germán Diago Oct 23 '14 at 09:35
  • This depends on the use case, it is not clear that it is only used in one compile unit. – CK1 Oct 23 '14 at 09:38
  • Yes, that is why I mentioned about the context :) – Germán Diago Oct 23 '14 at 09:39