Here is a solution creating an array of doubles which takes an initialization class to map an int index to a suitable value. The example create an array with 20 value approximating sin(x) for 20 values in the range [0, 2π]. Most of the code is devoted to producing a sequence of integers [0...N): if that operation is readily available, the code becomes fairly trivial (it is being added to C++14; see n3493).
#include <iostream>
#include <cmath>
template <int...> struct indices {};
template <int N, typename> struct make_list;
template <int... Indices>
struct make_list<0, indices<Indices...> > {
typedef indices<0, Indices...> type;
};
template <int N, int... Indices>
struct make_list<N, indices<Indices...> > {
typedef typename make_list<N-1, indices<N, Indices...> >::type type;
};
template <typename Init, int N, typename> struct array_aux;
template <typename Init, int N, int... Indices>
struct array_aux<Init, N, indices<Indices...> >
{
static double const values[N];
};
template <typename Init, int N, int... Indices>
double const array_aux<Init, N, indices<Indices...> >::values[N] = {
Init::value(Indices)...
};
template <typename Init, int N>
struct array
: array_aux<Init, N, typename make_list<N-1, indices<> >::type>
{
};
struct init_sin
{
static constexpr double value(int index) {
return std::sin(index * 2.0 * 3.1415 / 20.0);
}
};
int main()
{
for (int i = 0; i != 20; ++i) {
std::cout << array<init_sin, 20>::values[i] << "\n";
}
}
If the generator function, i.e., Init::value() is a constexpr function actually return constant values (probably not quite the case for std::sin()) the values can be computed at compile time. Otherwise they will be computed during static initialization.
unsignedin strategic places byfloat. What exactly did you try that you think it doesn't work?