C++ function template with ellipsis (Variadic)

7049 ワード

  • Start from something simple:

  • #include <stdarg.h> // va_list
    #include <stdio.h>

    void func( const char *str, ... );

    template< class TYPE, typename TO > bool FormTest( const TYPE str, TO i )
    {
    func( str, i );
    return true;
    }

    int main( void )
    {
    FormTest< char*, char* >( _("%s
    "), _("string") );
    }

    void func( const char *str, va_list &ap );

    void func( const char *str, ... )
    {
    va_list ap;
    va_start( ap, str );
    func( str, ap );
    va_end( ap );
    }

    void func( const char *str, va_list &ap )
    {
    const char *pek; int i;
    pek=va_arg( ap, const char* );
    printf( str, pek );
    }

  • From something more flexible yet still deterministic:
  • template<typename T>
    struct SVaPassNext{
    SVaPassNext<T> sibs;
    T dwObject;
    };
    template<> struct SVaPassNext<0>{};
    //SVaPassNext - is generator of structure of any size at compile time.


    class CVaPassNext{
    public:
    SVaPassNext<typename T> svapassnext;
    CVaPassNext(va_list & args){
    try{//to avoid access violation

    memcpy(&svapassnext, args, sizeof(svapassnext));
    } catch (...) {}
    }
    };
    #define va_pass(valist, T) CVaPassNext(valist).svapassnext<T>

    void func(const char *szFormat, ...)
    {
    va_list args;
    va_start(args, szFormat);
    func(szFormat, args);
     va_end(args);
    }
    void func( const char *str, va_list &ap )
    {
    wxObject*pek;
    pek = va_arg( va_pass(ap, wxObject*), wxObject* );
    ....
    }
    int main( void )
    {
    FormTest< char*, wxObject* >( _("id_of_MyObject"), &m_MyObject );
    }
  • How about from some underministic cases:

  • #include <iostream>
    #include <cstdarg>
    using namespace std;

    /*
    * The challenge: find the maximum value of a arbitrary list of values without
    * the use of the conditional-control structures.
    * NOTE: The use of the iif<T>() function was inspired
    * by Bench's int greatest(int, int) function using arrays to resolve a binary condition.
    * Bench also inspired the combination of a iif() and function pointers to make a function table to
    * avoid the use of any conditional control structure in the recursion.
    */

    //This simulates the ?: operator
    template <class T>
    T iif(bool condition, T true_val, T false_val) {
    T table[2];
    table[0] = false_val;
    table[1] = true_val;
    return table[condition];
    }

    // This will return the greater of the two values
    template <class T>
    T greatest( T first, T second )
    {
    return iif((first > second), first, second);
    }

    // This function marks the end of the recursion used in maximum_loop()
    template <class T>
    T terminatingFunction(va_list &args, int num, T theMax) { return theMax; }

    //This is a recursive function used to scroll thought the list or parameters
    template <class T>
    T maximum_loop(va_list &args, int num, T theMax) {
    T current = va_arg(args, T);
    theMax = greatest(theMax, current);
    //This is the ugliest line in the code, the "T (*)(va_list&, int, T)" is the type for the function pointers.
    // this line simulates the conditional function call:
    // return ((num > 1) ? &maximum_loop: &terminatingFunction)(args, num-1, theMax);
    return iif<T (*)(va_list&, int, T)>((num > 1), &maximum_loop, &terminatingFunction )(args, num-1, theMax);
    }

    //This function will return the maximum value of a variable number of elements.
    template <class T, int len>
    T maximum(T first, ...) {
    T theMax = first;
    va_list args;
    va_start(args, first);
    int length = len - 1; //One is used up by "first"
    theMax = maximum_loop<T>(args, length, theMax);
    va_end(args);
    return theMax;
    }


    int main() {
    double a = maximum<double, 11>(2.1, 1.2, 65.3, 10.4, 37.5, 6.0, 9.0, 24.0, 89.3, 89.5, 89.9);
    cout << endl << a << endl;
    system("Pause");
    return 0;
    }

  • How about these:

  • template<typename T>
    void print( const T& t )
    {
    std::cout << t;
    }

    template< typename T, typename... Args>
    void print( const T& t, const Args&... args )
    {
    print( t );
    print( args... );
    }

    template<typename... T>
    class tuple;
    template<typename T, typename... Ts>
    class tuple<T, Ts...>;
    template<>
    class tuple<>;