Simplify variadic template: Remove some specializations - c++

I found a template to calculate the binomial coefficient, which I happily used for function generation. The advantage is that I use this template for compile time Bernstein polynomial generation instead of using the derived polynomials (just 5 very simple ones).
I initially thought the code would become easier by doing so because the generation of the five random functions now obvious. Unfortunately, the code below is hard to read for someone not used to templates. Is there a way to get rid of at least some of the template specializations?
// Template functions to estimate the binominal coefficient
template<uint8_t n, uint8_t k>
struct binomial {
static constexpr int value = (binomial<n - 1, k - 1>::value + binomial<n - 1, k>::value);
};
template<>
struct binomial<0, 0> {
static constexpr int value = 1;
};
template<uint8_t n>
struct binomial<n, 0> {
static constexpr int value = 1;
};
template<uint8_t n>
struct binomial<n, n> {
static constexpr int value = 1;
};

You might probably use constexpr functions. Here is C++11-friendly version:
constexpr int factorial(int n)
{
return (n == 1) ? 1 : n * factorial(n - 1);
}
constexpr int bin_coeff(int n, int k)
{
return factorial(n) / factorial(n - k) / factorial(k);
}
EXAMPLE

Related

Code executable in compile time and runtime [duplicate]

Lets say that you have a function which generates some security token for your application, such as some hash salt, or maybe a symetric or asymetric key.
Now lets say that you have this function in your C++ as a constexpr and that you generate keys for your build based on some information (like, the build number, a timestamp, something else).
You being a diligent programmer make sure and call this in the appropriate ways to ensure it's only called at compile time, and thus the dead stripper removes the code from the final executable.
However, you can't ever be sure that someone else isn't going to call it in an unsafe way, or that maybe the compiler won't strip the function out, and then your security token algorithm will become public knowledge, making it more easy for would be attackers to guess future tokens.
Or, security aside, let's say the function takes a long time to execute and you want to make sure it never happens during runtime and causes a bad user experience for your end users.
Are there any ways to ensure that a constexpr function can never be called at runtime? Or alternately, throwing an assert or similar at runtime would be ok, but not as ideal obviously as a compile error would be.
I've heard that there is some way involving throwing an exception type that doesn't exist, so that if the constexpr function is not deadstripped out, you'll get a linker error, but have heard that this only works on some compilers.
Distantly related question: Force constexpr to be evaluated at compile time
In C++20 you can just replace constexpr by consteval to enforce a function to be always evaluated at compile time.
Example:
int rt_function(int v){ return v; }
constexpr int rt_ct_function(int v){ return v; }
consteval int ct_function(int v){ return v; }
int main(){
constexpr int ct_value = 1; // compile value
int rt_value = 2; // runtime value
int a = rt_function(ct_value);
int b = rt_ct_function(ct_value);
int c = ct_function(ct_value);
int d = rt_function(rt_value);
int e = rt_ct_function(rt_value);
int f = ct_function(rt_value); // ERROR: runtime value
constexpr int g = rt_function(ct_value); // ERROR: runtime function
constexpr int h = rt_ct_function(ct_value);
constexpr int i = ct_function(ct_value);
}
Pre C++20 workaround
You can enforce the use of it in a constant expression:
#include<utility>
template<typename T, T V>
constexpr auto ct() { return V; }
template<typename T>
constexpr auto func() {
return ct<decltype(std::declval<T>().value()), T{}.value()>();
}
template<typename T>
struct S {
constexpr S() {}
constexpr T value() { return T{}; }
};
template<typename T>
struct U {
U() {}
T value() { return T{}; }
};
int main() {
func<S<int>>();
// won't work
//func<U<int>>();
}
By using the result of the function as a template argument, you got an error if it can't be solved at compile-time.
A theoretical solution (as templates should be Turing complete) - don't use constexpr functions and fall back onto the good-old std=c++0x style of computing using exclusively struct template with values. For example, don't do
constexpr uintmax_t fact(uint n) {
return n>1 ? n*fact(n-1) : (n==1 ? 1 : 0);
}
but
template <uint N> struct fact {
uintmax_t value=N*fact<N-1>::value;
}
template <> struct fact<1>
uintmax_t value=1;
}
template <> struct fact<0>
uintmax_t value=0;
}
The struct approach is guaranteed to be evaluated exclusively at compile time.
The fact the guys at boost managed to do a compile time parser is a strong signal that, albeit tedious, this approach should be feasible - it's a one-off cost, maybe one can consider it an investment.
For example:
to power struct:
// ***Warning: note the unusual order of (power, base) for the parameters
// *** due to the default val for the base
template <unsigned long exponent, std::uintmax_t base=10>
struct pow_struct
{
private:
static constexpr uintmax_t at_half_pow=pow_struct<exponent / 2, base>::value;
public:
static constexpr uintmax_t value=
at_half_pow*at_half_pow*(exponent % 2 ? base : 1)
;
};
// not necessary, but will cut the recursion one step
template <std::uintmax_t base>
struct pow_struct<1, base>
{
static constexpr uintmax_t value=base;
};
template <std::uintmax_t base>
struct pow_struct<0,base>
{
static constexpr uintmax_t value=1;
};
The build token
template <uint vmajor, uint vminor, uint build>
struct build_token {
constexpr uintmax_t value=
vmajor*pow_struct<9>::value
+ vminor*pow_struct<6>::value
+ build_number
;
}
In the upcoming C++20 there will be consteval specifier.
consteval - specifies that a function is an immediate function, that is, every call to the function must produce a compile-time constant
Since now we have C++17, there is an easier solution:
template <auto V>
struct constant {
constexpr static decltype(V) value = V;
};
The key is that non-type arguments can be declared as auto. If you are using standards before C++17 you may have to use std::integral_constant. There is also a proposal about the constant helper class.
An example:
template <auto V>
struct constant {
constexpr static decltype(V) value = V;
};
constexpr uint64_t factorial(int n) {
if (n <= 0) {
return 1;
}
return n * factorial(n - 1);
}
int main() {
std::cout << "20! = " << constant<factorial(20)>::value << std::endl;
return 0;
}
Have your function take template parameters instead of arguments and implement your logic in a lambda.
#include <iostream>
template< uint64_t N >
constexpr uint64_t factorial() {
// note that we need to pass the lambda to itself to make the recursive call
auto f = []( uint64_t n, auto& f ) -> uint64_t {
if ( n < 2 ) return 1;
return n * f( n - 1, f );
};
return f( N, f );
}
using namespace std;
int main() {
cout << factorial<5>() << std::endl;
}

How to ensure constexpr function never called at runtime?

Lets say that you have a function which generates some security token for your application, such as some hash salt, or maybe a symetric or asymetric key.
Now lets say that you have this function in your C++ as a constexpr and that you generate keys for your build based on some information (like, the build number, a timestamp, something else).
You being a diligent programmer make sure and call this in the appropriate ways to ensure it's only called at compile time, and thus the dead stripper removes the code from the final executable.
However, you can't ever be sure that someone else isn't going to call it in an unsafe way, or that maybe the compiler won't strip the function out, and then your security token algorithm will become public knowledge, making it more easy for would be attackers to guess future tokens.
Or, security aside, let's say the function takes a long time to execute and you want to make sure it never happens during runtime and causes a bad user experience for your end users.
Are there any ways to ensure that a constexpr function can never be called at runtime? Or alternately, throwing an assert or similar at runtime would be ok, but not as ideal obviously as a compile error would be.
I've heard that there is some way involving throwing an exception type that doesn't exist, so that if the constexpr function is not deadstripped out, you'll get a linker error, but have heard that this only works on some compilers.
Distantly related question: Force constexpr to be evaluated at compile time
In C++20 you can just replace constexpr by consteval to enforce a function to be always evaluated at compile time.
Example:
int rt_function(int v){ return v; }
constexpr int rt_ct_function(int v){ return v; }
consteval int ct_function(int v){ return v; }
int main(){
constexpr int ct_value = 1; // compile value
int rt_value = 2; // runtime value
int a = rt_function(ct_value);
int b = rt_ct_function(ct_value);
int c = ct_function(ct_value);
int d = rt_function(rt_value);
int e = rt_ct_function(rt_value);
int f = ct_function(rt_value); // ERROR: runtime value
constexpr int g = rt_function(ct_value); // ERROR: runtime function
constexpr int h = rt_ct_function(ct_value);
constexpr int i = ct_function(ct_value);
}
Pre C++20 workaround
You can enforce the use of it in a constant expression:
#include<utility>
template<typename T, T V>
constexpr auto ct() { return V; }
template<typename T>
constexpr auto func() {
return ct<decltype(std::declval<T>().value()), T{}.value()>();
}
template<typename T>
struct S {
constexpr S() {}
constexpr T value() { return T{}; }
};
template<typename T>
struct U {
U() {}
T value() { return T{}; }
};
int main() {
func<S<int>>();
// won't work
//func<U<int>>();
}
By using the result of the function as a template argument, you got an error if it can't be solved at compile-time.
A theoretical solution (as templates should be Turing complete) - don't use constexpr functions and fall back onto the good-old std=c++0x style of computing using exclusively struct template with values. For example, don't do
constexpr uintmax_t fact(uint n) {
return n>1 ? n*fact(n-1) : (n==1 ? 1 : 0);
}
but
template <uint N> struct fact {
uintmax_t value=N*fact<N-1>::value;
}
template <> struct fact<1>
uintmax_t value=1;
}
template <> struct fact<0>
uintmax_t value=0;
}
The struct approach is guaranteed to be evaluated exclusively at compile time.
The fact the guys at boost managed to do a compile time parser is a strong signal that, albeit tedious, this approach should be feasible - it's a one-off cost, maybe one can consider it an investment.
For example:
to power struct:
// ***Warning: note the unusual order of (power, base) for the parameters
// *** due to the default val for the base
template <unsigned long exponent, std::uintmax_t base=10>
struct pow_struct
{
private:
static constexpr uintmax_t at_half_pow=pow_struct<exponent / 2, base>::value;
public:
static constexpr uintmax_t value=
at_half_pow*at_half_pow*(exponent % 2 ? base : 1)
;
};
// not necessary, but will cut the recursion one step
template <std::uintmax_t base>
struct pow_struct<1, base>
{
static constexpr uintmax_t value=base;
};
template <std::uintmax_t base>
struct pow_struct<0,base>
{
static constexpr uintmax_t value=1;
};
The build token
template <uint vmajor, uint vminor, uint build>
struct build_token {
constexpr uintmax_t value=
vmajor*pow_struct<9>::value
+ vminor*pow_struct<6>::value
+ build_number
;
}
In the upcoming C++20 there will be consteval specifier.
consteval - specifies that a function is an immediate function, that is, every call to the function must produce a compile-time constant
Since now we have C++17, there is an easier solution:
template <auto V>
struct constant {
constexpr static decltype(V) value = V;
};
The key is that non-type arguments can be declared as auto. If you are using standards before C++17 you may have to use std::integral_constant. There is also a proposal about the constant helper class.
An example:
template <auto V>
struct constant {
constexpr static decltype(V) value = V;
};
constexpr uint64_t factorial(int n) {
if (n <= 0) {
return 1;
}
return n * factorial(n - 1);
}
int main() {
std::cout << "20! = " << constant<factorial(20)>::value << std::endl;
return 0;
}
Have your function take template parameters instead of arguments and implement your logic in a lambda.
#include <iostream>
template< uint64_t N >
constexpr uint64_t factorial() {
// note that we need to pass the lambda to itself to make the recursive call
auto f = []( uint64_t n, auto& f ) -> uint64_t {
if ( n < 2 ) return 1;
return n * f( n - 1, f );
};
return f( N, f );
}
using namespace std;
int main() {
cout << factorial<5>() << std::endl;
}

C++ array as template parameter

I want to write a simple polynomial class that can take an array of coefficients and expand it into a function a compile time so I don't need to loop over the coefficients at run time. I want to do something like this:
template <PARAM_TYPE, PARAMS>
class P {
public:
PARAM_TYPE eval(PARAM_TYPE p){
//Does PARAMS[0] * pow(p, PARAMS.length() -1) + ... + PARAMS[N-1]
}
}
Sample call
P<double,{2,4,3}> quadratic;
quadratic.eval(5); //returns 73
I don't want to be doing the loop since that will take time. Ideally I want to be able to form the expression above at compile time. Is this possible? Thanks
Here is an example of doing what you want. The compiler is finicky about whether or not it optimizes away all the code into constants depending on the usage I noticed and which compiler you use.
test here
#include <type_traits>
template<class T, unsigned Exponent>
inline constexpr typename std::enable_if<Exponent == 0, T>::type
pow2(const T base)
{
return 1;
}
template<class T, unsigned Exponent>
inline constexpr typename std::enable_if<Exponent % 2 != 0, T>::type
pow2(const T base)
{
return base * pow2<T, (Exponent-1)/2>(base) * pow2<T, (Exponent-1)/2>(base);
}
template<class T, unsigned Exponent>
inline constexpr typename std::enable_if<Exponent != 0 && Exponent % 2 == 0, T>::type
pow2(const T base)
{
return pow2<T, Exponent / 2>(base) * pow2<T, Exponent / 2>(base);
}
template<typename ParamType>
inline constexpr ParamType polynomial(const ParamType&, const ParamType& c0)
{
return c0;
}
template<typename ParamType, typename Coeff0, typename ...Coeffs>
inline constexpr ParamType polynomial(const ParamType& x, const Coeff0& c0, const Coeffs& ...cs)
{
return (static_cast<ParamType>(c0) * pow2<ParamType, sizeof...(cs)>(x)) + polynomial(x, static_cast<ParamType>(cs)...);
}
unsigned run(unsigned x)
{
return polynomial(x, 2, 4, 3);
}
double run(double x)
{
return polynomial(x, 2, 4, 3);
}
unsigned const_unsigned()
{
static const unsigned value = polynomial(5, 2, 4, 3);
return value;
}
double const_double()
{
static const double value = polynomial(5, 2, 4, 3);
return value;
}
EDIT: I have updated the code to a use a tweaked version of pow2<>() that aggressively performs calculations at compile time. This version optimizes so well at -O2 that it actually surprised me. You can see the generated assembly for the full program using the button above the code. If all arguments are constant, the compiler will generate the entire constant value at compile time. If the first argument is runtime-dependent, it generates very tight code for it still.
(Thanks to #dyp on this question for the inspiration to pow)
To evaluate a polynom, a good algorithm is Horner (See https://en.wikipedia.org/wiki/Horner%27s_method). The main idea is to compute the polynom recursively. Let's a polynom P of order n with coefficient ai. It is easy to see that the sequence Pk = Pk-1*x0 + an-k with P0 = an, that P(x0) = Pn.
So let's implement this algorithm using constexpr function:
template<class T>
constexpr double horner(double x, T an) { return an; }
template<class... T, class U = T>
constexpr double horner(double x, U an, T... a) { return horner(x, a...) * x + an; }
std::cout << horner(5., 1, 2, 1) << std::endl;
//test if the invocation of the constexpr function takes the constant expression branch
std::cout << noexcept(horner(5., 1, 2, 1)) << std::endl;
As you see, it is really easy to implement the evaluation of a polynom with constexpr functions using the recursive formula.

fill static templated arrays with metaprogramming and variadic templates

I know that there are easier ways to do it, but
I would like to initialize at compilation time
the map from unrolled index of 2d array to its general format.
I would like to do this without needing to instansiate the array object.
Below I define the map from array[][]->array[].
Now I wonder how to do the opposite: [] -> [][]
without hardcoding the chosen mapping scheme.
I guess that should be possible using metaprogramming and variadic templates.
But I tried using it for the first time just a couple of days ago,
so it takes a while to get used to ;)
header:
template <int dim>
class internal {
static unsigned int table[dim][dim];
static unsigned int x_comp[dim*dim];
static unsigned int y_comp[dim*dim];
};
source:
//1d case:
template <>
unsigned int
internal<1>::table[1][1] = {{0}};
template <>
unsigned int
internal<1>::x_component[1] = {0};
template <>
unsigned int
internal<1>::y_component[1] = {0};
//2d case:
template<>
unsigned int
internal<2>::table[2][2] =
{{0, 1},
{2, 3}
};
// here goes some metaprogramming tricks to initialize
// internal<2>::y_component[2*2] = ...
// internal<2>::x_component[2*2] = ...
// based on mapping above, i.e. table[2][2];
// that is:
// x_table = { 0, 0, 1, 1 }
// y_table = { 0, 1, 0, 1 }
//
// so that :
//
// index == table[i][j]
// i == x_comp[index]
// j == y_comp[index]
EDIT1:
or just tell me that it's not possible and I hard-code everything or use
integer division to relate the two index representations.
EDIT2:
i would prefer to stick with definition of arbitrary arrays.
Of course one can do without, as in answer below using integer division.
Those arrays can be really arbitrary, for example:
template<>
unsigned int
internal<2>::table[2][2] =
{{3, 0},
{2, 1}
};
Using arrays:
Given a table with unique entries from 0 to dim^2-1, you can write constexpr lookup functions for the i and j of a given table entry:
constexpr unsigned get_x_comp(unsigned index, unsigned i=0, unsigned j=0)
{ return table[i][j] == index ? i : get_x_comp(index, ((j+1)%dim ? i : i+1), (j+1)%dim); }
constexpr unsigned get_y_comp(unsigned index, unsigned i=0, unsigned j=0)
{ return table[i][j] == index ? j : get_y_comp(index, ((j+1)%dim ? i : i+1), (j+1)%dim); }
These will recursively call themselves, iterating through the table and looking for index. Recursion will eventually end when the given index is found and i/j of that index is returned.
Combine that with the C++14 std::integer_sequence mentioned by Jonathan to initialize the arrays:
template<unsigned... I>
constexpr auto make_x_comp(std::integer_sequence<unsigned, I...>) -> std::array<unsigned, sizeof...(I)> { return {get_x_comp(I)...}; }
Using metafunctions instead of arrays:
In some cicumstances, one might not even need arrays. I assume you want to the table to contain consecutive indices from 0 to dim^2-1. If that's the case, table, x_comp and y_comp are only simple compiletime functions with the following attributes:
table(i,j) := i*dim + j
x_comp(index) := index / dim (integer division)
y_comp(index) := index % dim
Depending on if you have C++11 features available, the implementation will be different, but both times without arrays.
Note: the following implementations will assume that the numbers stored in table are consecutive from 0 to dim^2-1. If that is not the case, you'll have to roll your own appropiate function for table and use the above get_x_comp and get_y_comp implementatio
C++11:
template <unsigned dim> //use unsigned to avoid negative numbers!
struct internal {
static constexpr unsigned table(unsigned i, unsigned j) { return i*dim+j; }
static constexpr unsigned x_comp(unsigned index) { return index/dim; }
static constexpr unsigned y_comp(unsigned index) { return index%dim; }
};
You can call these functions like normal functions anywhere, especially anywhere you need compiletime constants. Example: int a[internal<5>::table(2,4)];
C++03:
template <unsigned dim> //use unsigned to avoid negative numbers!
struct internal {
template<unsigned i, unsigned j>
struct table{ static const unsigned value = i*dim+j; };
template<unsigned index>
struct x_comp{ static const unsigned value = index/dim; };
template<unsigned index>
struct y_comp{ static const unsigned value = index%dim; };
};
Using these metafunctions is a bit more clumsy than in C++11, but works as usual with template metafunctions. Same example as above: int a[internal<5>::table<2,4>::value];
Note: This time you can put the (meta-)functions in the header, since they are not non-integral static member variables any more. Also you do not need to restrict the template to small dimensions, since everything will be calculated well for dimensions less than sqrt(numeric_limits<unsigned>::max()).
I'm sorry if I'm not answering the question directly (or at all), but I don't really understand what you're asking. I think what you're saying is that you want to initialize at compilation time a way to have an array of size N x M represented as a 1D array?
I've included code that allows you to allocate non-square dimensions. I've built this in "easy" C++ so if you're just getting into templates it's not so difficult to follow.
Is it possible to do something like this?
template <typename T, typename std::size_t N, typename std::size_t M = 1>
class Array {
T* data;
public:
Array<T, N, M>() : data(new T[N * M]) {
T temp = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
data[i * M + j] = temp++;
}
}
}
/* methods and stuff
}
Where M is the column number, so you'd use this like:
int main(void) {
Array<float, 10, 10> myArray;
return 0;
}
Remember to call delete in the destructor.
Edit: I didn't understand the rule for populating x_comp and y_comp when I wrote this, now that I see that part of the question this answer is not really relevant, because I was incorrectly assuming table only contained consecutive integers. The answer is left here anyway because Arne's (much better) answer refers to it.
I would replace the arrays with std::array and use the C++14 integer_sequence utility:
template <int dim>
struct internal {
static std::array<std::array<unsigned, dim>, dim> table;
static std::array<unsigned, dim*dim> x_comp;
static std::array<unsigned, dim*dim> y_comp;
};
template<unsigned Origin, unsigned... I>
constexpr std::array<unsigned, sizeof...(I)>
make_1d_array_impl(std::integer_sequence<unsigned, I...>)
{
return { { I + Origin ... } };
}
template<int N>
constexpr std::array<unsigned, N*N>
make_1d_array()
{
return make_1d_array_impl<0>(std::make_integer_sequence<unsigned, N*N>{});
}
template<unsigned... I>
constexpr std::array<std::array<unsigned, sizeof...(I)>, sizeof...(I)>
make_2d_array_impl(std::integer_sequence<unsigned, I...> seq)
{
return { { make_1d_array_impl<I*sizeof...(I)>(seq) ... } };
}
template<int N>
constexpr std::array<std::array<unsigned, N>, N>
make_2d_array()
{
return make_2d_array_impl(std::make_integer_sequence<unsigned, N>{});
}
template<int dim>
std::array<std::array<unsigned, dim>, dim> internal<dim>::table = make_2d_array<dim>();
That fills the table array correctly. I'll have to think about it a bit more to populate x_comp and y_comp as you want, but it's doable.
You can find an C++11 implementation of integer_sequence at https://gitlab.com/redistd/integer_seq/blob/master/integer_seq.h

Is there a better way to fill array with precalculated values by templates (for using in runtime)?

So, assume I have a template structure-function fib<i>::value. I want to get nth fibonacci number in runtime. For this i create array fibs[] = { fib<0>::value, ... , fib<maxN>::value }. Unfortunatelly, for some functions maxN can be very large and I can't fill it with hands only. So I writed some preprocessor directives to make task easier.
#define fib(x) (fib<(x)>::value)
#define fibLine_level_0(x) fib(5*(x) + 0), fib(5*(x) + 1), fib(5*(x) + 2), fib(5*(x) + 3), fib(5*(x) + 4)
#define fibLine_level_1(x) fibLine_level_0(2*(x) + 0), fibLine_level_0(2*(x) + 1)
#define fibLine_level_2(x) fibLine_level_1(2*(x) + 0), fibLine_level_1(2*(x) + 1)
#define fibLine_level_3(x) fibLine_level_2(2*(x) + 0), fibLine_level_2(2*(x) + 1)
#define cAarrSize(x) (sizeof(x) / sizeof(x[0]))
And I use it so:
int fibs[] = { fibLine_level_3(0) };
for (int i = 0; i < cAarrSize(fibs); i++)
cout << "fib(" << i << ") = " << fibs[i] << endl;
The code that you may need:
template<int i>
struct fibPair{
static const int fst = fibPair<i-1>::snd;
static const int snd = fibPair<i-1>::fst + fibPair<i-1>::snd;
};
template<>
struct fibPair<0> {
static const int fst = 0;
static const int snd = 1;
};
template<int i>
struct fib {
static const int value = fibPair<i>::fst;
};
But this code is really ugly. What to do to make it more beautiful?
Constraints: this code must be used in sport programming. That means - no third-party libraries and sometimes no C++11 (but it can be)
Fib structure can be rewritten as follows:
template <size_t i>
struct fib
{
static const size_t value = fib<i - 1>::value + fib<i - 2>::value;
};
template <>
struct fib<0>
{
static const size_t value = 0;
};
template <>
struct fib<1>
{
static const size_t value = 1;
};
Compile-time array of the Fibonacci numbers can be calculated using C++11.
Edit 1 (changed the type of fib values).
Edit 2:
Compile-time generation of Fibonacci numbers array (based on this answer).
template<unsigned... args> struct ArrayHolder
{
static const unsigned data[sizeof...(args)];
};
template<unsigned... args>
const unsigned ArrayHolder<args...>::data[sizeof...(args)] = { args... };
template<size_t N, template<size_t> class F, unsigned... args>
struct generate_array_impl
{
typedef typename generate_array_impl<N-1, F, F<N>::value, args...>::result result;
};
template<template<size_t> class F, unsigned... args>
struct generate_array_impl<0, F, args...>
{
typedef ArrayHolder<F<0>::value, args...> result;
};
template<size_t N, template<size_t> class F>
struct generate_array
{
typedef typename generate_array_impl<N-1, F>::result result;
};
int main()
{
const size_t count = 10;
typedef generate_array<count, fib>::result fibs;
for(size_t i = 0; i < count; ++i)
std::cout << fibs::data[i] << std::endl;
}
All you need is to provide generate_array with the generation «function» (our fib struct).
Thanks to #nameless, for giving link to question, where I found answer by #MichaelAnderson for simple c++ (without new features). I used it and expanded for my own needs.
So, concept is simple, but a bit strange. We must produce recursive templated structure, where the first field is this same temlated structure with other argument.
template<size_t N>
struct FibList {
FibList<N-1> previous;
size_t value;
FibList<N>() : value(fib<N>::value) {}
};
Let's try expand it a bit (just to see, what compiler will produce):
template<size_t N>
struct FibList {
FibList<N-3> previous;
size_t value_N_minus_2;
size_t value_N_minus_1;
size_t value_N;
};
So we can think that FibList is array and just cast it (that is weak point of my solution - I can't prove this now)
static const size_t maxN = 2000;
FibList<maxN> fibList;
size_t *fibArray = &fibList.value - maxN;
Or in another way:
size_t *fibArray = reinterpret_cast<size_t*>(&fibList);
Important: size of array is maxN+1, but standart methodic to get array size (sizeof(array) / sizeof(array[0]) will fail. Be pretty accurate with that.
Now we must stop recursion:
// start point
template<>
struct FibList<0> {
size_t value;
FibList<0>() : value(0) {}
};
// start point
template<>
struct FibList<1> {
FibList<0> previous;
size_t value;
FibList<1>() : value(1) {}
};
Note, that swapping places of FibList<1> and FibList<0> will produce stack overflow in compiler.
And we must solve another problem - template recursion have limited depth (depends on compiler and/or options). But, fortunately, compiler have only depth limit, not memory limit for templates (well, yeah, memory limit is more bigger than depth limit). So we have obvious ugly solution - call fib<N> in series with step equal to depth limit - and we will never catch template depth limit about fib<N>. But we can't just write fib<500>::value not in runtime. So we got solution - write macro that will specialize FibList<N> using fib<N>::value:
#define SetOptimizePointForFib(N) template<>\
struct FibList<N> {\
FibList<(N)-1> previous;\
size_t value;\
FibList<N>() : value(fib<N>::value) {}\
};
And we must write something like this:
SetOptimizePointForFib(500);
SetOptimizePointForFib(1000);
SetOptimizePointForFib(1500);
SetOptimizePointForFib(2300);
So we got really compile time precalc and filling static arrays of awesome lengths.