Although you can't initialise an array in-place like that, you can do almost the same thing by creating a recursive struct:
template <int I>
struct squared {
squared<I - 1> rest;
int x;
squared() : x((I - 1) * (I - 1)) {}
};
template <>
struct squared<1> {
int x;
squared() : x(0) {}
};
Then later in your code you can declare:
squared<5> s;
and the compiler will indeed create a struct containing 5 ints: 0, 1, 4, 16, 25.
A couple of notes:
- My interpretation of the C++ standard is that it stops short of guaranteeing that this
struct will be laid out identically to an array. While it is a POD type, and POD types are guaranteed to be laid out "contiguously" in memory (1.8/5) with the first member at offset 0 (9.2/17) and later members at higher addresses (9.2/12), and arrays are also laid out "contiguously" (8.3.4/1), the standard doesn't say that arrays are layout-compatible with such structs. However, any sane compiler will lay these objects out identically.
- C++ requires that even an empty
struct be at least 1 byte long. If it did not, we could go with a slightly cleaner formulation in which the base case of the recursion was I == 0 and we didn't subtract 1 from I for the calculations.
It would be nice if we could place this struct inside a union with an array of the appropriate size, to make it easy to access the members. Unfortunately, C++ bans you from including an object in a union if that object has a non-trivial constructor. So the easiest way to get at the ith element is with a good old-fashioned cast:
squared<5> s;
cout << "3 squared is " << reinterpret_cast<int*>(&s)[3] << endl;
If you wanted, you could write an overloaded operator[]() function template to make this prettier.