问题
I am trying to write a macro to expand the contents of a struct:
struct Str
{
int a;
float f;
char *c;
};
Str s = {123, 456.789f, "AString"};
#define STRINGIFY_STR(x) ... // Macro to stringify x which is an instance of Str
printf("%s", STRINGIFY_STR(s));
desired output: [a: 123, f:456.789, c:AString]
Is it possible to write a macro that does this? If it is, then how?
回答1:
Is there a reason you want to do this as a macro?
You should write a function to perform this action instead of using the preprocessor.
Depending on your goals, there are a few options. The boost formatting library provides a great toolkit to build the formatted string. You could always overload operator<< to provide clean output, as well.
If you're doing this in pure C, the sprintf family of methods work for creating formatted output.
回答2:
This is quite gross, and only works on gcc
/g++
.
#define STRINGIFY_STR(x) \
std::string(({ std::ostringstream ss; \
ss << "[a: " << x.a \
<< ", f: " << x.f \
<< ", c: " << x.c << "]"; \
ss.str(); })).c_str()
You have to create the string from the values. Please don't do it this way. Please follow Reed's advice.
Here is how I would modify your struct
to allow it to be pretty printed:
struct Str
{
int a;
float f;
char *c;
std::ostream & dump (std::ostream &os) const {
return os << "[a: " << a
<< ", f: " << f
<< ", c: " << c << "]";
}
};
std::ostream & operator << (std::ostream &os, const Str &s) {
return s.dump(os);
}
Str s = {123, 456.789f, "AString"};
Now, to print out s
, you can use std::cout
:
std::cout << s << std::endl;
Or, if you really want a string:
std::stringstream ss;
s.dump(ss);
puts(ss.str().c_str());
回答3:
struct stringify
{
operator std::string() const
{
return str ;
}
std::string str ;
};
template < typename T > stringify operator+ ( stringify s, const T& object )
{
std::ostringstream stm ;
stm << object ;
if( !s.str.empty() && !std::isspace( *s.str.rbegin() ) ) s.str += ' ' ;
s.str += stm.str() ;
return s ;
}
回答4:
I'm also against the approach, but to answer the question:
#define STRINGIFY_STR(x) \
(std::string("[a: ") + std::to_string((long double)x.a) \
+ std::string(", f:") + std::to_string((long double)x.f) \
+ std::string(",c: ") + x.c + std::string("]") ).c_str()
I suggest writing a member function that does this though.
来源:https://stackoverflow.com/questions/11059881/write-a-macro-to-stringify-the-contents-of-a-struct