/* This value is set, by default to the max it can be set to avoid template instatiation depth greater than 17 when not used inside templates. 17 comes from the standard , Annex B.2, the second bullet from the end. This is only a recommendation, and implemenations are free to define almost anything as such. GCC uses 500 by default, but this can be set with the -ftemplate-depth flag. (That was, in fact, how this was tested to work for 17). EDG based compilers (Comeau, Intel) default to 60. */ const unsigned limit = 15;//475+ //Not a template to further reduce both clutter and depth issues //Also can be used when constant can be used at preprocess time //c_pow::val is used when decisions must be delayed until // instantiation time const unsigned l_0 = 1; const unsigned l_1 = limit * l_0; const unsigned l_2 = limit * l_1; const unsigned l_3 = limit * l_2; const unsigned l_4 = limit * l_3; const unsigned l_5 = limit * l_4; const unsigned l_6 = limit * l_5; template struct aval {}; //reduces instantiation depth issues #define makeaval(x) \ template \ struct aval { \ static const unsigned val = (N/l_ ## x) % limit; \ } makeaval(0); makeaval(1); makeaval(2); makeaval(3); makeaval(4); makeaval(5); makeaval(6); template struct c_pow {}; #define makepow(x) \ template<> \ struct c_pow { \ static const unsigned val = l_ ## x; \ } makepow(0); makepow(1); makepow(2); makepow(3); makepow(4); makepow(5); makepow(6); struct empty {}; template class F, unsigned N, unsigned PLACE> struct c_if { typedef T type; }; template class F, unsigned N, unsigned PLACE> struct c_if { typedef F type; }; //our wrap parameter N can be represented as a polynomial // a_n * limit^n for n starting at 0. //We will assume a limit of 10 here, for ease of notation. //we will use 999 as an example number. //999,0 inherits from every n,0 such that n < 999 //999,1 inherits from 990,1 //990,1 inherits from every n,1 such that n < 990 and 10 divides n //999,2 inherits from 900 //900,2 inherits from every n,2 such that n < 900 and 100 divides n //9,1 inherits from empty #define MAKECOUNT \ template \ struct wrap : public c_if<(N / c_pow::val) == 0, \ empty, \ wrap, \ (PLACE == 0) ? \ N-1 : \ ((aval::val == 0) ? \ (N - c_pow::val) : \ (aval::val * c_pow::val)), \ PLACE>::type { \ static const wrap * pass; \ }; \ template \ char (*test(const wrap<0,PLACE> * ))[1] MAKECOUNT; const unsigned DEDUCT = 1; #define GET6 0 #define GET5 ((sizeof *test(wrap::pass))-DEDUCT) #define GET4 ((sizeof *test(wrap::pass))-DEDUCT) #define GET3 ((sizeof *test(wrap::pass))-DEDUCT) #define GET2 ((sizeof *test(wrap::pass))-DEDUCT) #define GET1 ((sizeof *test(wrap::pass))-DEDUCT) #define GET0 ((sizeof *test(wrap::pass))-DEDUCT) #define GET GET0 #define GET_S ((sizeof *test(wrap::pass)) -DEDUCT) #define ISLIMIT(x) ((GET_S % l_ ## x) == 0) #define OVER(x) \ char (*test(const wrap *))[GET + 1 - (ISLIMIT(x) ? 0 : 1) + DEDUCT] #define SET \ char (*test(const wrap *))[GET+1+DEDUCT]; \ OVER(1); \ OVER(2); \ OVER(3); \ OVER(4); \ OVER(5)