#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <iomanip>

/** Range generation,
 * from http://stackoverflow.com/questions/13313980/populate-an-array-using-constexpr-at-compile-time **/
template<unsigned... Is> struct seq{};

template<unsigned N, unsigned... Is>
struct gen_seq : gen_seq<N-1, N-1, Is...>{};

template<unsigned... Is>
struct gen_seq<0, Is...> : seq<Is...>{};

/** A table consisting of indexes and values,
 * which will all be computed at compile-time **/
template<unsigned N>
struct Table
{
    unsigned indexes[N];
    double  values[N];
 
    static constexpr unsigned length = N;
};


template< typename LambdaType, unsigned... Is>
constexpr Table< sizeof...(Is) > TableGenerator(seq<Is...>, LambdaType evalFunc)
{
    return {{ Is... }, { evalFunc(Is)... }};
}

template<unsigned N, typename LambdaType>
constexpr Table<N> TableGenerator( LambdaType evalFunc )
{
    return TableGenerator(gen_seq<N>(), evalFunc);
}



/** Function that computes a value for each index **/
constexpr double myFunc( unsigned idx )
{ 
    return sin(0.2 * idx) + cos(0.5*idx);
}


int main()
{
    constexpr unsigned length = 100;
 
    // create compile-time table
    constexpr Table<length> table = TableGenerator<length>( myFunc );
 
    // print values in vertical form, pretty-looking ;)
    const double lineMult = 12;
    const double lineOffset = 30;
    for(auto v : table.values)
    {
        const unsigned numSpaces = (unsigned) ( lineOffset + v * lineMult + 0.5 );
        std::cout << std::setfill(' ') << std::setw( numSpaces ) << "o" << std::endl;
    }
 
    std::cout << std::endl;
 
    return 0;
}
