views:

334

answers:

4

is it possible to construct variadic arguments for function by overloading operator comma of the argument? i want to see an example how to do so.., maybe something like this:

template <typename T> class ArgList {
public:
    ArgList(const T& a);
    ArgList<T>& operator,(const T& a,const T& b);
}
//declaration
void myFunction(ArgList<int> list);

//in use:
myFunction(1,2,3,4);

//or maybe:
myFunction(ArgList<int>(1),2,3,4);
+1  A: 

Operators have a fixed number of parameters. You cannot change that. The comma operator takes two arguments. So no. You can roll a custom, cascading version though, with some effort.

dirkgently
A: 

No, it isn't. The list of values separated by the comma operator will be evaluated as a single value. For example:

1,2,3

will result in a single value, 3.

anon
that's what i want, the function still receive single value, but that value was constructed by operator comma, i see that it was possible to do MyObject object = (1,2,3), i thought it was possible to modify it to be working with MyObject as function argument
uray
@uray Sorry, that is completely unclear. Pleas modify your question to illustrate what you want to do. For example, what are the types of a,b,c and d in your example code? Remember, you cannot overload operators for the "built-in" types.
anon
@neil: i've edited my question
uray
+1  A: 

Maybe something like this:

class MyArgList {
public:   
     typedef std::list<boost::any> ManyList;

     template <typename T>
     MyArgList& operator, (const T& val) {
        elems.push_back(val);
        return *this; 
     }

     ManyList::iterator begin() {return elems.begin();}
       ...

private:
     ManyList elems;
};

Usage would be:

void foo(MyArgList& list);
foo((myArgList(),1,2,3,4,5));
Alexander Gessler
+6  A: 

It is sort-of possible, but the usage won't look very nice. For exxample:

#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>

template <class T>
class list_of
{
    std::vector<T> data;
public:
    typedef typename std::vector<T>::const_iterator const_iterator;
    const_iterator begin() const { return data.begin(); }
    const_iterator end() const { return data.end(); }

    list_of& operator, (const T& t) {
        data.push_back(t);
        return *this;
    }
};

void print(const list_of<int>& args)
{
    std::copy(args.begin(), args.end(), std::ostream_iterator<int>(std::cout, " "));
}

int main()
{
    print( (list_of<int>(), 1, 2, 3, 4, 5) );
}

This shortcoming will be fixed in C++0x where you can do:

void print(const std::initializer_list<int>& args)
{
    std::copy(args.begin(), args.end(), std::ostream_iterator<int>(std::cout, " "));
}

int main()
{
    print( {1, 2, 3, 4, 5} );
}

or even with mixed types:

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

template <class Arg1, class ...ArgN>
void print(const Arg1& a1, const ArgN& ...an)
{
    std::cout << a1 << ' ';
    print(an...);
}


int main()
{
    print( 1, 2.4, 'u', "hello world" );
}
UncleBens
that's cool, its in TR1 ?
uray
initializer_list? I'm not sure since it needs built-in support from the language to work. But both snippets already compile with GCC 4.4.1 with std=C++0x
UncleBens
can we have global static overloaded operator comma like : `template<typename T> T` ?
uray
As Neil already mentioned, not for *"built-in"* types, so you have to start the expressions with something like `list_of()`.
Georg Fritzsche
Another thing that would eliminate the need for extra parenthesis would be to use some other operator: `print(list_of<int>() % 1 % 2 % 3);` You could also use template type deduction, if the first item was given to a function returning a `list_of<T>`: `print(make_list_of(1) % 2 % 3);` But it is ugly in every way. If it was possible to simulate it nicely, C++0x wouldn't add the changes to the language.
UncleBens