В C ++ 11 (и особенно в C ++ 14) лучший способ инициализировать объекты во время компиляции - это использовать конструкторы constexpr
, а не играть в метаигры с системой типов.
struct MyObject {
int x_, y_;
constexpr MyObject(int x, int y) : x_(x), y_(y) { }
};
const MyObject array[] = { MyObject(1,2), MyObject(3,4) };
Вы также можете применить свою идею "функции генератора" здесь, если вы действительно хотите:
#include <stdio.h>
#if __cplusplus < 201400
template<size_t... II> struct integer_sequence { typedef integer_sequence type; };
template<size_t N, size_t... II> struct make_index_sequence;
template<size_t... II> struct make_index_sequence<0, II...> : integer_sequence<II...> {};
template<size_t N, size_t... II> struct make_index_sequence : make_index_sequence<N-1, N-1, II...> {};
#define HACK(x) typename x::type
#else
#include <utility> // the C++14 way of doing things
using std::integer_sequence;
using std::make_index_sequence;
#define HACK(x) x
#endif
struct MyObject {
int x_, y_;
constexpr MyObject(int x, int y) : x_(x), y_(y) { }
};
template<typename T, int N, T (*Func)(int), typename Indices>
struct GeneratedArrayHelper;
template<typename T, int N, T (*Func)(int), size_t... i>
struct GeneratedArrayHelper<T, N, Func, integer_sequence<i...>> {
static const T data[N]; // element i is initialized with Func(i)
};
template<typename T, int N, T (*Func)(int), size_t... i>
const T GeneratedArrayHelper<T,N,Func, integer_sequence<i...>>::data[N] =
{ Func(i)... };
template<typename T, int N, T (*Func)(int)>
struct GeneratedArray :
GeneratedArrayHelper<T, N, Func, HACK(make_index_sequence<N>)> {};
constexpr MyObject newObject(int i) { return MyObject(2*i, 2*i+1); }
int main() {
for (const MyObject& m : GeneratedArray<MyObject, 5, newObject>::data) {
printf("%d %d\n", m.x_, m.y_);
}
// Output:
// 0 1
// 2 3
// 4 5
// 6 7
// 8 9
}
Я не знаю, почему Clang 3.5 и GCC 4.8 настаивают на том, чтобы я добавил туда макрос HACK()
, но они отказываются компилировать код без него. Возможно, я совершил какую-то глупую ошибку, и кто-то может указать на это. Кроме того, я не уверен, что все const
и constexpr
находятся в лучших местах.