/* -*- c++ -*- This file is part of the dpp library of C++ template classes doc: http://diaxen.ssji.net/dpp/index.html repo: https://www.ssji.net/svn/projets/trunk/libdpp This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . (c) 2012 Alexandre Becoulet Some parts of this file were generated using tools/template_switch.pl */ #ifndef DPP_TEMPLATE_SWITCH_HH_ #define DPP_TEMPLATE_SWITCH_HH_ /** @file @module {Template switch} */ namespace dpp { /** @module {Template switch} @header dpp/template_switch @This declares a class designed to hold an array of function pointers for multiple instances of the same template function but with different values of its enum template parameter. The class constructor fill the array with function pointers for all enum values between 0 and @tt C0. The function pointer can later be retrieved using the @tt {()} operator on the template switch object. Other classes exists which hold multidimensional array to deal with multiple enum template parameters. @section {Examples} Use of template switch with global function and 1 enum parameter: @example test/test_template_switch.cc:example|example1 Use of template switch with member function and 2 enum parameters: @example test/test_template_switch.cc:example|example2 @end section */ #define DPP_TEMPLATE_SWITCH_1(clname, func_type, func, C0) \ class clname \ { \ typedef typeof(C0) e0; \ \ typedef func_type table_type[C0+1]; \ table_type _t; \ \ template \ struct iter; \ \ template \ struct iter \ { \ static void s(table_type &t) \ { \ } \ }; \ \ template \ struct iter \ { \ static void s(table_type &t) \ { \ t[I0] = &func<(e0)I0>; \ iter<2*I0+1, (2*I0+1 >= C0+1)>::s(t); \ iter<2*I0+2, (2*I0+2 >= C0+1)>::s(t); \ } \ }; \ \ public: \ \ clname() \ { \ iter<0, false>::s(_t); \ } \ \ const func_type operator() (e0 p0) const \ { \ return _t[p0]; \ } \ } /** @module {Template switch} @header dpp/template_switch @see #DPP_TEMPLATE_SWITCH_1 */ #define DPP_TEMPLATE_SWITCH_2(clname, func_type, func, C0, C1) \ class clname \ { \ typedef typeof(C0) e0; \ typedef typeof(C1) e1; \ \ typedef func_type table_type[C0+1][C1+1]; \ table_type _t; \ \ template \ struct iter; \ \ template \ struct iter \ { \ static void s(table_type &t) \ { \ } \ }; \ \ template \ struct iter \ { \ static void s(table_type &t) \ { \ t[I0][I1] = &func<(e0)I0, (e1)I1>; \ iter<2*I0+1, I1, (2*I0+1 >= C0+1)>::s(t); \ iter<2*I0+2, I1, (2*I0+2 >= C0+1)>::s(t); \ if (2*I0+1 == C0+1 || 2*I0+2 == C0+1) { \ iter<0, 2*I1+1, (2*I1+1 >= C1+1)>::s(t); \ iter<0, 2*I1+2, (2*I1+2 >= C1+1)>::s(t); \ } \ } \ }; \ \ public: \ \ clname() \ { \ iter<0, 0, false>::s(_t); \ } \ \ const func_type operator() (e0 p0, e1 p1) const \ { \ return _t[p0][p1]; \ } \ } /** @module {Template switch} @header dpp/template_switch @see #DPP_TEMPLATE_SWITCH_1 */ #define DPP_TEMPLATE_SWITCH_3(clname, func_type, func, \ C0, C1, C2) \ class clname \ { \ typedef typeof(C0) e0; \ typedef typeof(C1) e1; \ typedef typeof(C2) e2; \ \ typedef func_type table_type[C0+1][C1+1][C2+1]; \ table_type _t; \ \ template \ struct iter; \ \ template \ struct iter \ { \ static void s(table_type &t) \ { \ } \ }; \ \ template \ struct iter \ { \ static void s(table_type &t) \ { \ t[I0][I1][I2] = &func<(e0)I0, (e1)I1, (e2)I2>; \ iter<2*I0+1, I1, I2, (2*I0+1 >= C0+1)>::s(t); \ iter<2*I0+2, I1, I2, (2*I0+2 >= C0+1)>::s(t); \ if (2*I0+1 == C0+1 || 2*I0+2 == C0+1) { \ iter<0, 2*I1+1, I2, (2*I1+1 >= C1+1)>::s(t); \ iter<0, 2*I1+2, I2, (2*I1+2 >= C1+1)>::s(t); \ if (2*I1+1 == C1+1 || 2*I1+2 == C1+1) { \ iter<0, 0, 2*I2+1, (2*I2+1 >= C2+1)>::s(t); \ iter<0, 0, 2*I2+2, (2*I2+2 >= C2+1)>::s(t); \ } \ } \ } \ }; \ \ public: \ \ clname() \ { \ iter<0, 0, 0, false>::s(_t); \ } \ \ const func_type operator() (e0 p0, e1 p1, e2 p2) const \ { \ return _t[p0][p1][p2]; \ } \ } /** @module {Template switch} @header dpp/template_switch @see #DPP_TEMPLATE_SWITCH_1 */ #define DPP_TEMPLATE_SWITCH_4(clname, func_type, func, \ C0, C1, C2, C3) \ class clname \ { \ typedef typeof(C0) e0; \ typedef typeof(C1) e1; \ typedef typeof(C2) e2; \ typedef typeof(C3) e3; \ \ typedef func_type table_type[C0+1][C1+1][C2+1][C3+1]; \ table_type _t; \ \ template \ struct iter; \ \ template \ struct iter \ { \ static void s(table_type &t) \ { \ } \ }; \ \ template \ struct iter \ { \ static void s(table_type &t) \ { \ t[I0][I1][I2][I3] = &func<(e0)I0, (e1)I1, (e2)I2, (e3)I3>; \ iter<2*I0+1, I1, I2, I3, (2*I0+1 >= C0+1)>::s(t); \ iter<2*I0+2, I1, I2, I3, (2*I0+2 >= C0+1)>::s(t); \ if (2*I0+1 == C0+1 || 2*I0+2 == C0+1) { \ iter<0, 2*I1+1, I2, I3, (2*I1+1 >= C1+1)>::s(t); \ iter<0, 2*I1+2, I2, I3, (2*I1+2 >= C1+1)>::s(t); \ if (2*I1+1 == C1+1 || 2*I1+2 == C1+1) { \ iter<0, 0, 2*I2+1, I3, (2*I2+1 >= C2+1)>::s(t); \ iter<0, 0, 2*I2+2, I3, (2*I2+2 >= C2+1)>::s(t); \ if (2*I2+1 == C2+1 || 2*I2+2 == C2+1) { \ iter<0, 0, 0, 2*I3+1, (2*I3+1 >= C3+1)>::s(t); \ iter<0, 0, 0, 2*I3+2, (2*I3+2 >= C3+1)>::s(t); \ } \ } \ } \ } \ }; \ \ public: \ \ clname() \ { \ iter<0, 0, 0, 0, false>::s(_t); \ } \ \ const func_type operator() (e0 p0, e1 p1, e2 p2, e3 p3) const \ { \ return _t[p0][p1][p2][p3]; \ } \ } /** @module {Template switch} @header dpp/template_switch @see #DPP_TEMPLATE_SWITCH_1 */ #define DPP_TEMPLATE_SWITCH_5(clname, func_type, func, \ C0, C1, C2, C3, C4) \ class clname \ { \ typedef typeof(C0) e0; \ typedef typeof(C1) e1; \ typedef typeof(C2) e2; \ typedef typeof(C3) e3; \ typedef typeof(C4) e4; \ \ typedef func_type table_type[C0+1][C1+1][C2+1][C3+1][C4+1]; \ table_type _t; \ \ template \ struct iter; \ \ template \ struct iter \ { \ static void s(table_type &t) \ { \ } \ }; \ \ template \ struct iter \ { \ static void s(table_type &t) \ { \ t[I0][I1][I2][I3][I4] = &func<(e0)I0, (e1)I1, (e2)I2, (e3)I3, (e4)I4>; \ iter<2*I0+1, I1, I2, I3, I4, (2*I0+1 >= C0+1)>::s(t); \ iter<2*I0+2, I1, I2, I3, I4, (2*I0+2 >= C0+1)>::s(t); \ if (2*I0+1 == C0+1 || 2*I0+2 == C0+1) { \ iter<0, 2*I1+1, I2, I3, I4, (2*I1+1 >= C1+1)>::s(t); \ iter<0, 2*I1+2, I2, I3, I4, (2*I1+2 >= C1+1)>::s(t); \ if (2*I1+1 == C1+1 || 2*I1+2 == C1+1) { \ iter<0, 0, 2*I2+1, I3, I4, (2*I2+1 >= C2+1)>::s(t); \ iter<0, 0, 2*I2+2, I3, I4, (2*I2+2 >= C2+1)>::s(t); \ if (2*I2+1 == C2+1 || 2*I2+2 == C2+1) { \ iter<0, 0, 0, 2*I3+1, I4, (2*I3+1 >= C3+1)>::s(t); \ iter<0, 0, 0, 2*I3+2, I4, (2*I3+2 >= C3+1)>::s(t); \ if (2*I3+1 == C3+1 || 2*I3+2 == C3+1) { \ iter<0, 0, 0, 0, 2*I4+1, (2*I4+1 >= C4+1)>::s(t); \ iter<0, 0, 0, 0, 2*I4+2, (2*I4+2 >= C4+1)>::s(t); \ } \ } \ } \ } \ } \ }; \ \ public: \ \ clname() \ { \ iter<0, 0, 0, 0, 0, false>::s(_t); \ } \ \ const func_type operator() (e0 p0, e1 p1, e2 p2, e3 p3, e4 p4) const \ { \ return _t[p0][p1][p2][p3][p4]; \ } \ } /** @module {Template switch} @header dpp/template_switch @see #DPP_TEMPLATE_SWITCH_1 */ #define DPP_TEMPLATE_SWITCH_6(clname, func_type, func, \ C0, C1, C2, C3, C4, C5) \ class clname \ { \ typedef typeof(C0) e0; \ typedef typeof(C1) e1; \ typedef typeof(C2) e2; \ typedef typeof(C3) e3; \ typedef typeof(C4) e4; \ typedef typeof(C5) e5; \ \ typedef func_type table_type[C0+1][C1+1][C2+1][C3+1][C4+1][C5+1]; \ table_type _t; \ \ template \ struct iter; \ \ template \ struct iter \ { \ static void s(table_type &t) \ { \ } \ }; \ \ template \ struct iter \ { \ static void s(table_type &t) \ { \ t[I0][I1][I2][I3][I4][I5] = &func<(e0)I0, (e1)I1, (e2)I2, (e3)I3, (e4)I4, (e5)I5>; \ iter<2*I0+1, I1, I2, I3, I4, I5, (2*I0+1 >= C0+1)>::s(t); \ iter<2*I0+2, I1, I2, I3, I4, I5, (2*I0+2 >= C0+1)>::s(t); \ if (2*I0+1 == C0+1 || 2*I0+2 == C0+1) { \ iter<0, 2*I1+1, I2, I3, I4, I5, (2*I1+1 >= C1+1)>::s(t); \ iter<0, 2*I1+2, I2, I3, I4, I5, (2*I1+2 >= C1+1)>::s(t); \ if (2*I1+1 == C1+1 || 2*I1+2 == C1+1) { \ iter<0, 0, 2*I2+1, I3, I4, I5, (2*I2+1 >= C2+1)>::s(t); \ iter<0, 0, 2*I2+2, I3, I4, I5, (2*I2+2 >= C2+1)>::s(t); \ if (2*I2+1 == C2+1 || 2*I2+2 == C2+1) { \ iter<0, 0, 0, 2*I3+1, I4, I5, (2*I3+1 >= C3+1)>::s(t); \ iter<0, 0, 0, 2*I3+2, I4, I5, (2*I3+2 >= C3+1)>::s(t); \ if (2*I3+1 == C3+1 || 2*I3+2 == C3+1) { \ iter<0, 0, 0, 0, 2*I4+1, I5, (2*I4+1 >= C4+1)>::s(t); \ iter<0, 0, 0, 0, 2*I4+2, I5, (2*I4+2 >= C4+1)>::s(t); \ if (2*I4+1 == C4+1 || 2*I4+2 == C4+1) { \ iter<0, 0, 0, 0, 0, 2*I5+1, (2*I5+1 >= C5+1)>::s(t); \ iter<0, 0, 0, 0, 0, 2*I5+2, (2*I5+2 >= C5+1)>::s(t); \ } \ } \ } \ } \ } \ } \ }; \ \ public: \ \ clname() \ { \ iter<0, 0, 0, 0, 0, 0, false>::s(_t); \ } \ \ const func_type operator() (e0 p0, e1 p1, e2 p2, e3 p3, e4 p4, e5 p5) const \ { \ return _t[p0][p1][p2][p3][p4][p5]; \ } \ } } #endif