Reputation: 55870
I'm a fan of debug printing when trying to investigate problems in my code:
cout << "foo:" << foo << "bar:" << bar << "baz:" << baz;
Since I write code like this very often, it would be awesome if I could make it generic and easier to type. Maybe something like this:
DEBUG_MACRO(foo, bar, baz);
Even though foo
, bar
, and baz
resolve to variable names, not strings, is it possible to use their variable names to create the strings "foo:"
, "bar:"
, and "baz:"
? Can you write a function or macro that takes an unspecified number of parameters?
Upvotes: 5
Views: 229
Reputation: 8822
#define DEBUG_MACRO(name) std::cout << #name << " = " << name << std::endl;
Example: http://ideone.com/agw4i
Upvotes: 1
Reputation: 88801
If you have C++11 you can do something typesafe and fairly neat with variadic templates, e.g.:
#include <string>
#include <iostream>
template <typename T>
void debug(const T& v) {
std::cout << v << "\n";
}
template <typename T, typename... Tail>
void debug(const T& v, const Tail& ...args) {
std::cout << v << " ";
debug(args...);
}
#define NVP(x) #x":", (x)
int main() {
int foo=0;
double bar=0.1;
std::string f="str";
debug(NVP(foo),NVP(bar),NVP(f));
}
The NVP macro here is entirely optional and only needed if you want to print the name you referred to it by in the code as well.
If you really want to skip the NVP bit you can use the Boost pre-processor library (or roll your own) e.g.:
#include <string>
#include <iostream>
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
template <typename T>
void debug_impl(const T& v) {
std::cout << v << "\n";
}
template <typename T, typename... Tail>
void debug_impl(const T& v, const Tail& ...args) {
std::cout << v << " ";
debug_impl(args...);
}
#define NVP(x) #x":", (x)
#define MEMBER( r, data, i, elem ) BOOST_PP_COMMA_IF( i ) NVP(elem)
#define debug( members ) \
debug_impl( \
BOOST_PP_SEQ_FOR_EACH_I( MEMBER,, members ) \
)
int main() {
int foo=0;
double bar=0.1;
std::string f="str";
debug((foo)(bar)(f));
}
for the price of some slightly odd syntax. My example is based on this answer. I tried to use variadic macros to solve this directly as a "pure" C++11 solution, but it turns out recursing through a list is trickier than you'd hope with it.
Upvotes: 4
Reputation: 101506
Can you write a function that takes an unspecified number of parameters?
Yes, but usually you shouldn't.
You can declare a function that takes an unspecified number of parameters by using the elipses in the declaration:
int foo(string foo, ...)
But there are big problems with this. The biggest problem is that it breaks type safety. Consider what happens when you use another function with an unspecified parameter list incorrectly:
int n = 42;
char buf[256] = {};
sprintf(buf, "%s", n);
This is a bug -- I've specified a string, but passed an int
. Best case scenario is this will be executed the first time I debug my program and explode immediately. Much more likely however is that the code will never run until the first time an exceptional condition arises in production, and then it will take your whole program down in the middle of the trading day. Clients will call and yell at you, cancel units, etc... OK, I'm being dramatic, but the point is type safety is your friend, even when you have a love-hate relationship with it.
Upvotes: 0