From: daniel.kruegler@googlemail.com   
      
   Am 02.03.2012 21:59, schrieb Thomas Richter:   
   > Dear experts,   
   >   
   > is there a nice (template ?) trick to generate functions with variable   
   > number of arguments without using varargs (and hence, no type-checks)?   
   > The use case would be to generate functions for   
   >   
   > class Argument;   
   >   
   > class Caller {   
   > void Launch(Argument arg1);   
   > void Launch(Argument arg1,Argument arg2);   
   > void Launch(Argument arg1,Argument arg2,Argument arg3);   
   > // and so on   
   > };   
   >   
   > without the code repetition as in the above case. Arguments are all   
   > identical in type, but their number may grow very large and I don't want   
   > to repeat the same type of code all over again.   
      
   For a C++11 compiler variadic templates seem to be a natural solution:   
      
   class Argument;   
      
   class Caller {   
    template   
    void Launch(Arg... arg);   
   };   
      
   It is possible to realize that only particular types are valid arguments   
   for such function template or a maximum/minimum number of arguments.   
   Consider:   
      
   #include    
      
   template   
   struct and_;   
      
   template<>   
   struct and_<> : std::true_type   
   {   
   };   
      
   template   
   struct and_ : P   
   {   
   };   
      
   template   
   struct and_ : std::conditional::type   
   {   
   };   
      
   template   
   struct and_ : std::conditional, P1>::type   
   {   
   };   
      
   class Argument{};   
      
   struct Caller {   
    template...,   
   std::integral_constant 0)>>::value   
    >::type   
    >   
    void Launch(Arg... arg){}   
   };   
      
   int main() {   
    Argument arg1, arg2;   
    Caller c;   
    c.Launch(arg1); // OK   
    c.Launch(arg1, arg2); // OK   
    c.Launch(); // Error   
   }   
      
   An alternative approach but also requiring a C++11 compiler would be to   
   use a single function taking an initializer_list:   
      
   #include    
      
   class Argument{};   
      
   struct Caller {   
    void Launch(std::initializer_list arg){}   
   };   
      
   int main() {   
    Argument arg1, arg2;   
    Caller c;   
    c.Launch({arg1}); // OK   
    c.Launch({arg1, arg2}); // OK   
   }   
      
   The disadvantage of this approach is, that you are *required* to provide   
   the argument list in braces.   
      
   HTH & Greetings from Bremen,   
      
   Daniel Krügler   
      
      
   --   
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
    [ comp.lang.c++.moderated. First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|