Reputation: 335
To quickly insert brief debug statements I would like to turn
print("%d %d %s") % i % j % str;
into the more verbose
std::cout << boost::format("%d %d %s") % i % j % str << std::endl;
The mentioned #define print std::cout<<boost::format
does not have the endl, so even if I add a "\n" to the string the buffers are not flushed if a crash occurs on the next line.
The more C++-ish approach to have
print("string)
return an xPrint instance and overload xPrint::operator%
does not work because I have no way of knowing when the last %
call has been made and it is time to print the resulting format string.
Note: I need boost::format, so a printf/fflush won't do, and I'd like the resulting syntax to be brief.
Upvotes: 0
Views: 329
Reputation: 1053
I would suggest something like
#define print(x) std::cout << (x) << std::endl
which allows you to do
print(boost::format("%s") % str);
If you really insist on the brief version given above the closest thing I can come up with is this:
#include <iostream>
#include <boost/format.hpp>
class Forwarder
{
public:
Forwarder(const std::string& s)
: f(s)
{}
template <typename T>
Forwarder& operator%(const T& t)
{
f % t;
return *this;
// You could even return a reference to f here instead if you wanted
}
~Forwarder()
{
std::cout << f << std::endl;
}
private:
boost::format f;
};
#define print(x, y) { Forwarder f(x); f % y; }
int main()
{
std::string str("Hallo");
int i = 123, j = 456;
print("%s %d %d", str % i % j);
}
EDIT Here are some more (potentially dangerous!) ideas for hacking such a print statement. Code below is just to show the concepts and won't compile as is. Use at your own risk!
a) Add a terminating statement to Forwarder
by adding a specialization for operator%
instead of using the destructor to trigger printing:
Define helper struct as terminator (better be in a namespace, but you get the idea...):
struct END {};
Specialize template:
template <>
Forwarder& Forwarder::operator%<END>(const END& t)
{
std::cout << f << std::endl;
return *this;
}
Usage:
print("%s %d %d") % str % i % j % END;
b) Use an operator with less strict binding and right to left associativity. You'd have to introduce a helper type though which could be some kind of logging target.
void operator<<=(Logger& l, const Forwarder& f) { ... }
Usage:
DebugLogger <<= Forwarder("%s %d %d") % str % i % j;
c) The same as above but using the comma operator (yuck!) which has left to right associativity.
void operator,(const Forwarder& f, Logger& l) { ... }
Usage:
Forwarder("%s %d %d") % str % i % j, DebugLogger;
Upvotes: 2