I have a Visual Studio 2008 C++ dll where I would like to accept a variable number of arguments and know the type of each one. For example:
__declspec( dllexport ) void Foo( const char* object, const char* function, ... )
{
printf( "%s::%s( ", object, function );
va_list list;
va_start( list, function );
while( va_arg( list, ??? ) )
{
printf( "[%s] %s ", type, value );
}
va_end( list );
printf( " )\r\n" );
}
The expected usage is something like this:
Buzz api;
int a = 1;
api.DoSomething( a, "hello", 0.2f );
Foo( "Buzz", "DoSomething", a, "hello", 0.2f );
Where the expected output would look like this:
Buzz::DoSomething( 开发者_JS百科[int] 1, [const char*] "hello", [float] 0.2 )
Is this, or something like it, possible with RTTI? If a variadic argument solution is not possible (and I suspect it is not), I'm okay with one that includes multiple overloads for 1-n arguments.
Thanks, PaulH
First: "C" style variadic functions are supported in C++ for compatibility with C code only. It is not recommended that you should use them in new C++ code as they cannot enforce type safety.
A variadic function passes all of its "..." arguments as untyped values on the stack, The types of the values you pass as parameters must be deduced by the logic that you (as author of that function) put into the function you write. That is, the only thing that tells printf the types of the parameters (those that follow the format string) is the format string itself.
This is as true in C++ as it is in C. There is no way for RTTI to provide any type information for arbitrary values on the stack.
If the values were all pointers to objects (instances of related classes) within a class hierarchy then you could use a dynamic_cast to determine the types ... but you'd have to write code to handle the different classes yourself, the language would not do that for you.
A variadic argument solution is possible, but not the C way and not in the current version of the language. If your compiler implements variadic templates though, you could do it with them. You can mimic variadic templates with current version up to some arbitrary maximum (set by a variable if you use preprocessor magic) by having a function with a long list of default arguments.
So, depending on which way you want to go you need to learn variadic templates and/or the preprocessor. The former will become obvious once you do the research necessary. The latter is a bit tougher, but if you look at the src to things like boost::function it will become apparent.
精彩评论