/*
The Table template class helps to construct constexpr arrays of unsigned int values that support random-access using indices computed at runtime. Example: #include <iostream> #include "Table.hpp" template<unsigned int I> struct ComputeSquare { static constexpr unsigned int value = I * I; }; constexpr unsigned int N = 10; using Squares = Table<N, ComputeSquare>; int main() { for (unsigned int i = 0; i < N; ++i) { std::cout << Squares::val[i] << std::endl; } } */ #ifndef TABLE_HPP #define TABLE_HPP /* helper template for the Table template to construct an constexpr array filled with values F<0>::value .. F<N-1>::value; this template works recursively, i.e. - F<I+1>::value ... F<N>::value have already been computed and are passed as unsigned int ... values - F<0>::value ... F<I>::value are to be computed */ template<unsigned int I, unsigned int N, template<unsigned int> class F, unsigned int ... values> struct TableConstructor; /* this special case with I == 0 ends the recursion, i.e. we insert F<0>::value in front of values... which represent F<1>::value ... F<N-1>::value */ template<unsigned int N, template<unsigned int> class F, unsigned int ... values> struct TableConstructor<0, N, F, values...> { static constexpr unsigned int len = N; typedef unsigned int type[len]; /* note that the static member val is defined below at the end of this header file */ static constexpr type val = {F<0>::value, values...}; }; /* recursive case with I > 0 where - values... represent F<I+1>::value ... F<N-1>::value and - F<I>::value is inserted in the front */ template<unsigned int I, unsigned int N, template<unsigned int> class F, unsigned int ... values> struct TableConstructor : public TableConstructor<I-1, N, F, F<I>::value, values...> { }; /* Table is used to create a constexpr table with N elements that is filled with the values F<0>::value to F<N-1>::value using the TableConstructor helper template */ template<unsigned int N, template<unsigned int> class F> struct Table : public TableConstructor<N-1, N, F> { }; /* definition of the static member val of the TableConstructor template; if we do not have this, we have no support for a random access of the table with indices computed at runtime */ template<unsigned int N, template<unsigned int> class F, unsigned int ... values> constexpr typename TableConstructor<0, N, F, values...>::type TableConstructor<0, N, F, values...>::val; #endif |