C++ convert variables to template arguments -


i use templates optimization described here. however, growing number of bool template arguments, instantiating template might have many branches. , gets more branchy if use larger enums instead of bools.

#include <iostream> using namespace std;  template <bool b1, bool b2> int heavyloop_impl(int arg) {     (int = 0; < 10000000; i++)     {         // b1 known @ compile-time, branch eliminated         if (b1) { arg += 1; }         else    { arg += 2; }          // b2 known @ compile-time, branch eliminated         if (b2) { arg += 10; }         else    { arg += 20; }     }     return arg; }  // function generated automatically void heavyloop(bool b1, bool b2, int arg) {     int res;     if (b1) {         if (b2) { res = heavyloop_impl<true, true>(arg); }         else    { res = heavyloop_impl<true, false>(arg); }     } else {         if (b2) { res = heavyloop_impl<false, true>(arg); }         else    { res = heavyloop_impl<false, false>(arg); }     }     cout << "res: "<<res<<endl; }  int main(int argc, char**argv) {     bool b1 = true;     bool b2 = false;     int arg = 0;     heavyloop(b1, b2, arg);     return 0; } 

is there way automatically generate heavyloop function? this:

vars_to_template_function<bool, bool>(heavyloop_impl, b1, b2, arg); 

would possible somehow? hints.

note: simplified example. actual loop is of course more complicated :o)

i decided have more fun code, here's improved version on first attempt has following benefits:

  • supports enum types
  • explicitly specify how many parameters should converted
  • generic implementation complicated part, 1 small helper each function uses it.

the code:

#include <iostream> #include <utility> #include <type_traits>  // enum support enum class tribool { false, true, file_not_found };  // declare basic generic template // (independent of specific function you'd call) template< template< class > class cb, std::size_t n, typename = std::tuple<> > struct var_to_template;  // register types should supported template< template< class > class cb, std::size_t n, typename... cs > struct var_to_template< cb, n, std::tuple< cs... > > {     // bool pretty simple, there 2 values     template< typename r, typename... args >     static r impl( bool b, args&&... args )     {         return b           ? var_to_template< cb, n-1, std::tuple< cs..., std::true_type > >::template impl< r >( std::forward< args >( args )... )           : var_to_template< cb, n-1, std::tuple< cs..., std::false_type > >::template impl< r >( std::forward< args >( args )... );     }      // each enum, need register values     template< typename r, typename... args >     static r impl( tribool tb, args&&... args )     {         switch( tb ) {         case tribool::false:           return var_to_template< cb, n-1, std::tuple< cs..., std::integral_constant< tribool, tribool::false > > >::template impl< r >( std::forward< args >( args )... );         case tribool::true:           return var_to_template< cb, n-1, std::tuple< cs..., std::integral_constant< tribool, tribool::true > > >::template impl< r >( std::forward< args >( args )... );         case tribool::file_not_found:           return var_to_template< cb, n-1, std::tuple< cs..., std::integral_constant< tribool, tribool::file_not_found > > >::template impl< r >( std::forward< args >( args )... );         }         throw "unreachable";     }      // in theory add int, long, ...     // you'd have switch on every possible value want support! };  // terminate recursion template< template< class > class cb, typename... cs > struct var_to_template< cb, 0, std::tuple< cs... > > {     template< typename r, typename... args >     static r impl( args&&... args )     {         return cb< std::tuple< cs... > >::template impl< r >( std::forward< args >( args )... );     } };  // here's function template parameters template< bool b, tribool tb > int heavyloop_impl( int arg ) {     for( int = 0; < 10000000; i++ ) {         arg += b ? 1 : 2;         arg += ( tb == tribool::true ) ? 10 : ( tb == tribool::false ) ? 20 : 30;     }     return arg; }  // helper class, required once per function you'd forward template< typename > struct heavyloop_callback; template< typename... cs > struct heavyloop_callback< std::tuple< cs... > > {     template< typename r, typename... args >     static r impl( args&&... args )     {         return heavyloop_impl< cs::value... >( std::forward< args >( args )... );     } };  // , here, comes together: int heavyloop( bool b, tribool tb, int arg ) {     // provide helper , number of arguments     // should converted var_to_template<>     // , provide return type impl<>     return var_to_template< heavyloop_callback, 2 >::impl< int >( b, tb, arg ); }  int main() {     bool b = true;     tribool tb = tribool::false;     int arg = 0;     int res = heavyloop( b, tb, arg );     std::cout << "res: " << res << std::endl;     return 0; } 

and here's live example in case want play it.


Comments

Popular posts from this blog

java.util.scanner - How to read and add only numbers to array from a text file -

rewrite - Trouble with Wordpress multiple custom querystrings -