Jump to content
  • Advertisement
Sign in to follow this  
jamesleighe

Functions With a Variable Number of Args

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to write a function that will allow me to write things like:

Log ("This is the ", cstring, " test.");
Log ("This is the ", cstring, " test.", cstring, "Oh god!");

Where the function can take a variable number of arguments (always cstrings however).


I have tried va_list but va_start requires the number of variables as input? Can I do it without explicitly supplying that?

Share this post


Link to post
Share on other sites
Advertisement
You can do this with C++11 varargs features, or just by defining a bunch of overloads of Log(...), if it's not a preprocessor macro. Make a function with a bunch of parameters having an empty default value. Generally speaking when a function gets called, there's nothing that tells it how many arguments it has. It either gets that from one of the early arguments, the way printf does, or it just knows how many it's supposed to get, the way most functions are, or the last argument is followed by a special value such as NULL, the way execl and execlp do on some POSIX systems.

Share this post


Link to post
Share on other sites
Assuming C++, although you can do this using similar techniques in other languages:

template <typename T>
void LogActual(const T& contents)
{
std::cout << contents;
}

struct LogProxy
{
template <typename T>
LogProxy operator () (const T& contents)
{
LogActual(contents);
return LogProxy();
}
};

template <typename T>
LogProxy Log(const T& contents)
{
LogActual(contents);
return LogProxy();
}

int main()
{
Log("This ")("is ")("a ")("test.\n");
}



Although at this point, you may as well just use the C++ idiom of using the << operator for streamed output...

Share this post


Link to post
Share on other sites
I use this function:


//------------------------------------------------------------------------
inline std::string format( const char *szText, ... ) {

// Get the message with arguments
char szBuffer[1024] = {0};

va_list ap;
va_start(ap, szText);
_vsnprintf_s(szBuffer,1023, 1023, szText, ap);
va_end(ap);

return std::string(szBuffer);

}



To use this you would do: std::string strOutput = format( "This is the %s test. %s Oh god!", cstring1.c_str(), cstring2.c_str() );

Share this post


Link to post
Share on other sites
Assuming you are using C++, you can use some BOOST_PP trickery to do this while retaining type safety:


// log.h
#include <iostream>
#include <boost/preprocessor/library.hpp>

#define MAKEARG(z, n, arg) << BOOST_PP_CAT(arg, n)
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 8, "log_pp.h"))
#include BOOST_PP_ITERATE()
#undef MAKEARG



// log_pp.h
template <BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), typename T)>
inline void log(std::ostream& os, BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), const T, &arg))
{
os BOOST_PP_REPEAT(BOOST_PP_ITERATION(), MAKEARG, arg);
}



// log.cpp
#include "log.h"

int main(int argc, char* argv[])
{
log(std::clog, "this", "is", "a", "test");
return 0;
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!