# function with unknow number of arguments fails to use templates

This topic is 3670 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

hi, language : C++ ; VS.net 2008 on Vista; I'm writing an improved (for my needs anyway) version of OutputDebugString(). you give it a string and an unknown number of arguments ,teh '%' in the string will be replace by the argument :
void DebugOutput (tstring str, ...)
{
va_list args;
va_start(args, str);
tstringstream output;

for (int i = 0;i<(int)str.length();i++)
if (str.at(i) == '%')
{
int temp = va_arg(args,int);
output<<temp;
}else	output<<str.at(i);

va_end(args);
output<<endl;
OutputDebugString(output.str().c_str());
} 
as you see it works only with integers .. I want to make it a template, so I can give up any type of argument I like... so :
template <class DATATYPE>
void DebugOutput (tstring str, ...)
{  // ...
if (str.at(i) == '%')
{
DATATYPE temp = va_arg(args,DATATYPE);
//...
that won't work :( I got a compile error saying ;
Quote:
 Error 1 error C2783: 'void DebugOutput(std::wstring,...)' : could not deduce template argument for 'DATATYPE' d:\gsp xtra\vmf parser\les08-cameraskyboxapp_student\vmf_file.cpp 30
somebody knows how to fix this ?

##### Share on other sites
How do you call DebugOutput? Do you specify DATATYPE explicitly like this:
DebugOutput<int>("string % % %",2,5,44); // DATATYPE = int

You may find Boost Format library useful.

##### Share on other sites
DELETED

I didn't realise it was the function call you were talking about Kambiz, my mistake :)

##### Share on other sites
Quote:
 Original post by KambizHow do you call DebugOutput? Do you specify DATATYPE explicitly like this:*** Source Snippet Removed ***

that works :) Looks like I'm having a blond day :P
I didn't do this c'se normally the compiler fills it in..

is there also a way to work around this ?
Like if I want to passe different types :
DebugOutput<// ??> (_T("string"),5, 3.9, 9.3f );

##### Share on other sites
Quote:
 Original post by Yourselfis there also a way to work around this ?Like if I want to passe different types :DebugOutput (_T("string"),5, 3.9, 9.3f );

No, there's no way around this. Variadic functions are supported for backwards compatibility mostly. They're not designed to interact efficiently with modern C++ features, such as templates (this is because modern C++ uses operator overloading and chaining instead of variadic functions, for type-inference reasons).

So you'll have to provide one template argument for every one of them. For instance, you would have to define an overload of DebugOutput that takes at least three arguments, along with the appropriate template arguments:
DebugOutput<int,double,float>(/* args */);

Of course, this will require you to define a new version of DebugOutput for every different number of arguments, at which point you might as well give up on variadic functions altogether. Simply put, the point of a variadic function is to pass an arbitrary number of arguments without knowing the type of those arguments. If you need the type, then you lose any benefits of variadic functions, and might be interested by other solutions.

##### Share on other sites
I'm working on a personal tracing system and I ended up with this:

#define NCODE_TRACER_STR(_oss_,vArg)    (_oss_.GetStream().str(""), _oss_.GetStream()<<vArg, _oss_.GetStream().str())

For that you need a CFormatString object that I provide, but is just a wrapper over an std::ostringstream.

The way I choose was to rely on << operator to generate string data. For example, you could do this:

CFormatString oFormatString;NCODE_TRACER_STR(oFormatString, 2 << " HOLA " << false);NCODE_TRACER_STR(oFormatString, 3 <<" asd " << 3.43*2.2135234232343432423234);oFormatString.GetStream().precision(20);NCODE_TRACER_STR(oFormatString, true << " " << 3.43*2.21123323123123123123213);NCODE_TRACER_STR(oFormatString, std::showpos << std::scientific << 2 << " " << -23 << " " << 2.32);

All the above macros will provide a string object. If you want to have a look to the way it works you can check the library at www.ncode.byaku.net/tracer. It's open so you get the sources.

[Edited by - surfi on November 25, 2008 8:18:21 AM]

##### Share on other sites
There is also another problem, something like
DebugOutput<int>("%", 2.6);

would not cause any compile time error, although the argument has a wrong type.

Do it the c++ way using operator overloading or use boost format.

##### Share on other sites
They are going to introduce variadic templates in C++0x though, so there's a need to support variadic functions but with the benefit of type safety.

Currently, some things in boost seem to declare some things with ~20 template arguments and then probably use extensive metaprogramming magic/preprocessor to trim the unused ones (e.g boost::variant).

1. 1
2. 2
3. 3
4. 4
Rutin
13
5. 5

• 26
• 11
• 9
• 9
• 11
• ### Forum Statistics

• Total Topics
633701
• Total Posts
3013435
×

## Important Information

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!