2

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< class 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 );
}
2
  • If that's the source of the function, why not just junk it and put the functionality in Foo() yourself? Half the function is just variable arguments handling. Commented Dec 10, 2010 at 20:20
  • @DeadMG - That's not the complete function. DLL_Foo() will process the information and use to to alter the state of an object that is passed in as a handle, then return it as a handle. If that isn't at odds with your suggestion, can you elaborate more on what you mean? Commented Dec 10, 2010 at 20:27

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Not quite. If he had access to Boost.PP and Boost.MPL he could do it too. Technically you could just look at how Boost.MPL implements vector and code your own. You basically would have to re-implement parts of MPL and PP yourself.
It doesn't have to be truly variadic. A fixed upper limit solution is acceptable. 0..6 parameters, for example should be fine.
1

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.

1 Comment

@Éric - std::TR1 doesn't appear to be in our SDK. To clarify, I can use the standard library and the windows SDK and C++ language features available to the VS2008 compiler. I believe boost will compile and run. I just can't use it (yes, I hate this limitation, too). So, I will likely need to implement some small part of the voodo that is boost.MPL to get this done. I just don't know what that is.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.