Function with variable number of parameters via template

2

I know that the templates in function definitions makes, for each configuration that it allows, to compile a different function.

I want to know if it is possible to create functions with a varied number of parameters in such a way that it compiles a specific function for that parameter configuration.

I mean, you can do something that follows a logic like this, without needing libraries and that manages the optimized code especially for that specific "n".

template< int n >
int min( int arg[0] , int arg[1] , ... , int arg[n-1] ){
    int _min = (-1<<31)-1 , i ;
    for( i=0 ; i<n ; i++ )
        if( arg[i]<_min )
            _min = arg[i] ;
    return _min ;
}
    
asked by anonymous 03.08.2017 / 22:29

1 answer

3

Yes, it is possible, with variadic template :

template <typename T, typename... Args> T
min_vt(T x)
{
    return x;
}

template <typename T, typename... Args> T
min_vt(T x, T y, Args... args)
{
    T z = min_vt(y, args...);
    return x < z ? x : z;
}

But there are other ways to do something similar to what you want. See below.

Using variable argument lists ( va_list ), which works in pure C too, but you need to specify the amount of arguments passed to the function:

template <typename T> T
min_va(int nargs, ...)
{
    va_list ap;
    va_start(ap, nargs);
    T val = va_arg(ap, T);
    for (int i = 2; i <= nargs; i++) {
        T a = va_arg(ap, T);
        if (a < val)
            val = a;
    }
    va_end(ap);
    return val;
}

Using functor that returns the object itself:

template <typename T>
class
min_functor
{
private:
    T value;
public:
    min_functor(T v)
        : value(v)
    {
    }

    min_functor &operator()(T v) {
        if (v < value)
            value = v;
        return *this;
    }

    friend ostream &
    operator<<(ostream &os, min_functor<T> rhs)
    {
        os << rhs.value;
        return os;
    }
};

Manually implementing the same function with different amounts of arguments received:

template <typename T> T
min_multisig(T a0, T a1)
{
    return a0 < a1 ? a0 : a1;
}

template <typename T> T
min_multisig(T a0, T a1, T a2)
{
    return min_multisig(min_multisig(a0, a1), a2);
}

template <typename T> T
min_multisig(T a0, T a1, T a2, T a3)
{
    return min_multisig(min_multisig(min_multisig(a0, a1), a2), a3);
}

And the code to test:

int
main()
{
    cout << min_vt(1234, 1222) << endl;
    cout << min_vt(12.34, 12.22, 13.33) << endl;

    cout << min_va<int>(2, 1234, 1222) << endl;
    cout << min_va<double>(3, 12.34, 12.22, 13.33) << endl;

    cout << min_functor<int>(1234)(1222) << endl;
    cout << min_functor<double>(12.34)(12.22)(13.33) << endl;

    cout << min_multisig<int>(1234, 1222) << endl;
    cout << min_multisig<double>(12.34, 12.22, 13.33) << endl;

    return 0;
}
    
04.08.2017 / 01:30