2

Is it possible to generate an array at compile time, like in this nice answer of G. Fritzsche: Georg Fritzsche

but with floating point values?

I think its not possible in this manner because, the variadic expansion which happens by the recursion needs compile time const values?

Is there another way to generate compile time floating point arrays, with meta functions which calculate something complex at compile time or is this restricted only to arithmetic of integral types?

Thanks for the input! :-)

Community
  • 1
  • 1
Gabriel
  • 8,990
  • 6
  • 57
  • 101
  • 3
    Sure. Just replace the `unsigned` in strategic places by `float`. What exactly did you try that you think it doesn't work? – Dietmar Kühl Dec 04 '13 at 22:48
  • @DietmarKühl: You sure? :) –  Dec 04 '13 at 22:52
  • @VladLazarenko: yes. Note that I didn't say _all_ places! I said _strategic_ places. Primarily, you just change the declaration and the definition of the array. I would personally also chip in a transformation function for the fun of it. – Dietmar Kühl Dec 04 '13 at 22:56
  • Here's one of my constexpr array creation methods applied to floating-point numbers: http://stackoverflow.com/a/19016627/420683 there are probably a *lot* of duplicates for this kind of thing – dyp Dec 04 '13 at 23:15

2 Answers2

3

It wasn't possible in standard-compliant C++ when Georg wrote his answer, but with C++11 we can now do compile-time computation with floating-point and other numeric types.

The trick is to use constexpr functions instead of non-type template parameters.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
3

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.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • How can I check if the values are really computed during compile-time ? – Gabriel Dec 05 '13 at 00:35
  • 2
    @Gabriel: generally, look at the generated assembly. See if the code is there or a data table. – Sean Middleditch Dec 05 '13 at 01:29
  • I posted the assembly code, with high level output, I am not skilled: Where do I have to look for, there should be a data-table right?, because I only generated the table with the index in init_sin. link is : http://pastebin.com/284gVx4C – Gabriel Dec 05 '13 at 09:54
  • ---> Ahh found it, it is on line: 163 - 172 – Gabriel Dec 05 '13 at 10:02