I have a Visual Studio 2008 C++ DLL that exports a function that accepts a variadic parameter like this:
__declspec( dllexport ) void DLL_Foo( int count, ... )
{
va_list list;
va_start( list, count );
for( ; count; --count )
{
const wchar_t* item = va_arg( list, const wchar_t* );
if( count % 2 == 0 )
printfW( L"[%s] ", item );
else
printfW( L"%s ", item );
}
va_end( list );
printfW( L"\r\n" );
}
The expected usage is something like this:
DLL_Foo( 4, L"int", L"1", L"const wchar_t*", L"Hello" );
Where the output would be:
[int] 1, [const wchar_t*] Hello
To simplify the usage of this function, I intend to include a C++ template function like this:
template< class T1, class T2 >
void Foo( T1 p1, T2 p2 )
{
std::wstringstream t1W;
t1W << typeid( p1 ).name();
std::wstringstream p1W;
p1W << p1;
std::wstringstream t2W;
t2W << typeid( p2 ).name();
std::wstringstream p2W;
p2W << p2;
::DLL_Foo( 4, t1W.str().c_str(), p1W.str().c_str(), t2W.str().c_str(), p2W.str().c_str() );
};
Where the expected usage is like this:
int a = 1;
const wchar_t* b = L"Hello";
Foo( a, b );
With the same expected output as before.
Is there a template recursion method I can employ so that I don't have to implement a different template<> Foo()
function for 0..n parameters?
template<> void Foo();
template< class T1 > void Foo( T1 p1 );
template< cl开发者_运维技巧ass T1, ..., class N > void Foo( T1 p1, ..., N n );
Please, no solutions involving variadic templates or other C++0x features. I realize they're wonderful, but I'm using VS2008. Also, just to be more difficult, I cannot make use of boost functionality like boost::MPL.
Thanks, PaulH
Edit: Yes, the DLL actual dll function does more than print the type and value information. The actual DLL function looks a bit more like this:
__declspec( dllexport ) void DLL_Foo( MYHANDLE handle, int count, ... )
{
CMyObject* obj = reinterpret_cast< CMyObject* >( handle );
va_list list;
for( va_start( list, count ); count; --count )
{
const wchar_t* item = va_arg( list, const wchar_t* );
if( count % 2 == 0 )
{
obj->AddTypeInfo( item );
}
else
{
obj->AddValueInfo( item );
}
}
va_end( list );
}
This is only possible using C++0x features. If you cannot use its variadic templates, you cannot create a function … uh, that takes a variable number of templates.
On the other hand, you can create multiple overloads of the same method, each with its own number of arguments (1 … some upper limit). That’s of course quite a bit of work.
Konrad's answer is right.
However, you could avoid writing the multiple overloads at the cost of a slight inconvenience for your users by having Foo
accept a tuple, something like:
template<class TupleT>
void Foo(const TupleT& Args)
And ask the caller to wrap the arguments in a tuple when calling Foo:
//Foo(an_int, a_bool, a_whatever);
Foo(boost::make_tuple(an_int, a_bool, a_whatever));
... and now, right as I am about to click the "Post Your Answer" button, I see that you can't use Boost. Can you use the feature pack? I think it has std::tr1::tuple.
The last time I needed to do something like this I wrote a perl script that would generate the templates for me.
Downside is you end up with a lot of code to compile, but it depends on what your max is.
精彩评论