3

Is it possible to write a macro which can take in a variable number of arguments and expands like this :

quickdebug(a)   ->  cout << #a ": " << a;
quickdebug(a,b) ->  cout << #a ": " << a << #b ": "<< b;

etc

If not, is it possible for me to at least print all the arguments without giving format strings. e.g

quickdebug2(a)   -> cout << a ;
quickdebug2(a,b) -> cout << a << " " << b ;

etc

For example in java I can write a function which provides me similar functionality:

void debug(Object...args) 
{
  System.out.println(Arrays.deepToString(args));
}
4
  • In Java you cannot do #a. So the analogy is incorrect. You can accomplish what you did in Java with variadic templates in C++ (or multiple non variadic templates). Commented Dec 25, 2011 at 11:42
  • What I did in Java is an analogy for quickdebug2. And using variadic templates, I dont understand how can I find out the size & type of arguments. I mean I wish to be able to use it like this as well(which I can do in Java) : debug(42, "inner", 23.2) Commented Dec 25, 2011 at 11:47
  • "using variadic templates, I dont understand how can I find out the size & type of arguments" Heh? That's what variadic templates are for. Commented Dec 25, 2011 at 12:53
  • An example of this is the printf variadic template in Wikipedia. Your version would go something like this: void quickdebug() { } template<typename A, typename... B> void quickdebug(A a, B... b) { std::cout << a; quickdebug(b...); } Commented Jan 4, 2012 at 0:21

2 Answers 2

7

By using a class that overrides , operator:

class VariadicToOutputStream
{
public:
    VariadicToOutputStream(std::ostream& s, const std::string& separator = " ") : m_stream(s), m_hasEntries(false), m_separator(separator) {}
    template<typename ObjectType>
    VariadicToOutputStream& operator , (const ObjectType& v)
    {
        if (m_hasEntries) m_stream << m_separator;
        m_stream << v;
        m_hasEntries=true;
        return *this;
    }
    ~VariadicToOutputStream()
    {
        m_stream << std::endl;
    }

private:
    std::ostream& m_stream;
    bool m_hasEntries;
    std::string m_separator;
};

You can write for instance:

VariadicToOutputStream(std::cout) , 1, 0.5f, "a string";

This can then be wrapped with a preprocessor macro:

#define VARIADIC_TO_STDOUT(...)     VariadicToOutputStream(std::cout),__VA_ARGS__;

So you can write:

VARIADIC_TO_STDOUT(1, 0.5f, "a string");

It would be easy to add f.i. separator strings to be used between arguments.

Edit: I just added a default space as separator string.

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

2 Comments

Thanks Robert, for the magic. This is probably the coolest C++ hack I've ever seen. Hail! :)
I've made a small change : I've created a destructor for this class that prints a new line. So every macro call when returns prints a new line in the end. If you wish so, you might edit it in your answer as well =)
1

It is possible to make a macro that is variadic thus taking a variable amount of arguments. The syntax is similar to that of a function:

#define quickdebug(...) functiontocall("test", __VA_ARGS__)

Any argument listed after the last named argument in the argument list will be listed in __VA_ARGS__ including any seperating comma.

So: quickdebug(1, 2, "123", 4.5) becomes functioncall("test", 1, 2 , "123", 4.5)

However at some point you need to use these arguments, and here it can become extremely difficult if you don't have a format string, or something else indicating the type of the arguments.

The problem is that when reading variables from a variable arguments list, you need to know the type of the argument, or at least its size. If I were you I would choose a different approach.

You can read more about variadic macros here: http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html

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.