问题
I need to record (for auditing/logging purposes) the code of lambda functions that get passed around in my code. Of course, the lambda object also needs to be saved. So I came up with a macro solution as follows:
#define LAMBDA_AND_STRING(lambda) lambda, #lambda
using namespace std;
int main(int argc, const char * argv[])
{
auto p = pair<function<void()>, string> ( LAMBDA_AND_STRING( [] {
cout << "Hello world!" << endl;
cout << "Hello again!";
} ) );
cout << "CODE:" << endl << p.second << endl << endl;
cout << "EXECUTION:" << endl;
p.first();
cout << endl;
}
This outputs:
CODE:
[] { cout << "Hello world!" << endl; cout << "Hello again!"; }
EXECUTION:
Hello world!
Hello again!
That is almost good, but the newlines from the lambda definition are gone (in reality my lambdas are much longer than in the above prototypical example, so keeping the newlines is needed for reasons of readability). Any ideas on how to keep them? (C++11 is fine).
Thanks!
回答1:
If I remember correctly, the new lines aren't even part of the argument passed to the macro. It's to do with the order in which whitespace-folding occurs relative to macro expansion, and in effect whitespace is stripped during preprocessor tokenization.
foo.cpp:
#define FOO(a) a
FOO(
one
two
three
)
Result:
$ gcc -E foo.cpp
# 1 "foo.cpp"
# 1 "<command-line>"
# 1 "foo.cpp"
one two three
So you're out of luck, I think. You can do something really nasty to work around it:
#define LAMBDA_AND_STRING(lambda) lambda, #lambda
#define NEWLINE
LAMBDA_AND_STRING( [] { NEWLINE
cout << "Hello world!" << endl; NEWLINE
cout << "Hello again!"; NEWLINE
} )
Preprocesses to:
[] { cout << "Hello world!" << endl; cout << "Hello again!"; }, "[] { NEWLINE cout << \"Hello world!\" << endl; NEWLINE cout << \"Hello again!\"; NEWLINE }"
Now replace the NEWLINE
s in the string before printing.
来源:https://stackoverflow.com/questions/19741257/c-preprocessor-stringification-that-preserves-newlines