Banach Tarski Banach Tarski - 2 months ago 16
C++ Question

C++ Function to print any number of arguments

I came across this function below written in C++. A call to the function

trace()
with any number of arguments prints the values of each of these arguments alongside the name of the argument in the format

name1 : value1 | name2 : value2 and so on.

I wanted to learn how this code is working and what some of the syntax like the double ampersand
&&
,
__VA_ARGS__
meant. Thanks!

#define tr(...) trace(#__VA_ARGS__, __VA_ARGS__)

template <typename Arg1>
void trace(const char* name, Arg1&& arg1){
cout << name << " : " << arg1 << endl;
}

template <typename Arg1, typename... Args>
void trace(const char* names, Arg1&& arg1, Args&&... args){
const char* comma = strchr(names + 1, ',');
cout.write(names, comma-names) << " : " << arg1 << " | " ;

trace(comma+1, args...);
}

Answer
#define tr(...) trace(#__VA_ARGS__, __VA_ARGS__)

is a function macro that accepts a variable number of arguments.
It forwards a stringified version as the first argument.
There is no way to derive a string representation without using the preprocessor.

Example evaluation:

int main(){
    int i;
    float f;
    std::string s;
    tr(i,f,s);
}

resolves to:

int main(){
    int i;
    float f;
    std::string s;
    trace("i,f,s", i,f,s);
}

The two variadic template functions unroll each argument and calls itself recursively.

The base case function that ends the recursion is:

template <typename Arg1>
void trace(const char* name, Arg1&& arg1){
    cout << name << " : " << arg1 << endl;
}

This could be done more cleanly with a fold expression.

&& is used to allow perfect forwarding.