Functions with varying number of arguments

D

dima

Hello All!

Does anybody know anything about type-safe implementation of functions
with varying number of arguments?
I know one old solution - elipsis (stdarg,h). But it is NOT type-safe!

Thanks!
 
A

Alf P. Steinbach

* (e-mail address removed):
Does anybody know anything about type-safe implementation of functions
with varying number of arguments?
I know one old solution - elipsis (stdarg,h). But it is NOT type-safe!

It all depends.

Consider std::cout. It doesn't use any magic (well, it does, for
initialization, but not for argument passing!). Yet it supports an
arbitrary number of arguments of different types.

First, the most basic, simply overload a function:

void foo() {}
void foo( int ) {}
void foo( int, std::string ) {}

and so on.

Second, supporting an unlimited number of arguments of the same type,

void foo( FooArgs const& args ) {}

where FooArgs is a class like (add access restrictions as appropriate)

struct FooArgs
{
FooArgs& operator()( int aValue )
{
myValues.push_back( aValue );
return *this;
}

std::vector< SharedPtr< Value const* > > values;
};

so that you could call foo like

foo( FooArgs()( 1 )( 2 )( 3 ) );

or you might use the comma operator or e.g. the << operator instead of
the function call operator.

That's the basic idea of chaining calls, letting each operator call
return a reference to the object so that the same or some other operator
can be applied to the result again, which is used by std::cout.

Third, for just transferring an arbitrary bunch of arguments to some
other function (especially a constructor), nothing beats a macro:

#define FOO( args ) SomeOtherThing args

which you'd call like

FOO( (1, 2, 3) );

And there are other techniques.

It all depends.
 
A

Alf P. Steinbach

* Alf P. Steinbach:
std::vector< SharedPtr< Value const* > > values;

Obviously I didn't mean to write SharedPtr... in there. That was
because I contemplated sketching something more general. Which I didn't
do, so that should just be a std::vector<int>.

Sorry.
 
T

TB

Alf P. Steinbach sade:
* (e-mail address removed):

It all depends.

Consider std::cout. It doesn't use any magic (well, it does, for
initialization, but not for argument passing!). Yet it supports an
arbitrary number of arguments of different types.

First, the most basic, simply overload a function:

void foo() {}
void foo( int ) {}
void foo( int, std::string ) {}

and so on.

Second, supporting an unlimited number of arguments of the same type,

void foo( FooArgs const& args ) {}

where FooArgs is a class like (add access restrictions as appropriate)

struct FooArgs
{
FooArgs& operator()( int aValue )
{
myValues.push_back( aValue );
return *this;
}

std::vector< SharedPtr< Value const* > > values;
};

Or a more generic approach:

#include <boost/any.hpp>
struct FooArgs
{
template<typename T>
FooArgs& operator()( T const & aValue )
{
myValues.push_back( aValue );
return *this;
}
so that you could call foo like

foo( FooArgs()( 1 )( 2 )( 3 ) );

foo( FooArgs()( 1 )( 2.0 )( '3' )( "4" )( L"5" ) );
 
A

Alf P. Steinbach

* Pete Becker:
Read the original question, still quoted above.

I know you aren't that stupid, hence, you're just quarreling. Cheer up,
Pete. Have a beer!
 
P

Pete Becker

Alf said:
* Pete Becker:



I know you aren't that stupid, hence, you're just quarreling. Cheer up,
Pete. Have a beer!

The original question asked about FUNCTIONS that take a varying number
of arguments. Your first sentence was about cout, which is not a
function, and didn't mention that it's not a function. That is at best
confusing. Don't post when you've been drinking.
 
A

Alf P. Steinbach

* Pete Becker:
The original question asked about FUNCTIONS that take a varying number
of arguments. Your first sentence was about cout, which is not a
function, and didn't mention that it's not a function. That is at best
confusing. Don't post when you've been drinking.

The answer was all about functions, including several examples.

But you apparently didn't see that, and apparently didn't even see the
relevance of std::cout, and seem to be in a quarreling mode.

Whatever, have fun.
 
P

Pete Becker

Alf said:
* Pete Becker:



The answer was all about functions, including several examples.

But you apparently didn't see that, and apparently didn't even see the
relevance of std::cout, and seem to be in a quarreling mode.

Whatever, have fun.

Plonk.
 
D

Dumaiu

Glad we got that out of the way!
The buzzword you're looking for is 'variadic function.' Yes,
everybody likes them. No, the legacy <cstdarg> doesn't work very well.
The only way to achieve type safety is to chain the parameters by
return value, as Mr. Steinbach showed. std::cout overloads <<() to
provide the chaining token; the Boost libraries use %(), probably
because it's such a rare operator. The process can be templated, but
the first argument must be a "feeder" object of predictable type, such
as Mr. Steinbach's 'FooArgs'. For that reason, cout could have been
implemented to be called this way:

console_out( cout << arg << arg1 << arg2 );

but when you see how wordy this is, you see that it makes more sense to
do away with the parentheses and let the feeder, cout, masquerade as
the function name. std::cout is a function call, even if it isn't
implemented as one.
It isn't considered mature, but you can get as wild as you like with
operator overloading; e.g. (I just made this up),

FuncName / arg1, arg2, arg3;

which expands into

operator,( operator, (operator/ (FuncName, arg1), arg2), arg3);

But if you *really* want the look 'n' feel of a magic function, combine
this technique with a variadic macro. Look up 'variadic macro' on
Wikipedia.

Hope this helps,

J J-S
 
G

Greg

Hello All!

Does anybody know anything about type-safe implementation of functions
with varying number of arguments?
I know one old solution - elipsis (stdarg,h). But it is NOT type-safe!

Declare a function template and pass it a std::tr1:tuple that contains
(from 0 to 10) arguments.

Greg
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top