Joe*_*Joe 1 c++ macros c-preprocessor
我正在尝试使用宏在ostringstream中本地排队一个日志行,然后在行结束时转储该ostringstream的全部内容.但是,我仍然希望使用流插入语法.所以我想像这样变成一个日志行:
std::cerr << "Some error in my function. Code is " << errCode << " exiting" << std::endl;
Run Code Online (Sandbox Code Playgroud)
......进入这个
SERR("Some error in my function. Code is " << errCode << " exiting);
Run Code Online (Sandbox Code Playgroud)
我有一些简单的东西,效果很好.也就是说,直到我把它放在if-else语句中.显然我的宏观很糟糕,但我不知道该怎么做.
这是一个小样本程序,黑客攻击以说明问题:
#include <iostream>
#include <sstream>
#define SERR(x) { std::ostringstream _s; ; _s << x << std::endl; std::cerr << _s.str(); }
int main()
{
std::cout << "Hello World!\n";
bool val = false;
if (val)
SERR("No error");
else
SERR("Error");
}
Run Code Online (Sandbox Code Playgroud)
我从这个示例中的编译器获得的错误消息是:
1> c:\ users\joe\source\repos\consoleapplication5\consoleapplication5\consoleapplication5.cpp(15):错误C2181:非法其他没有匹配if
我有什么想法在这里错了吗?
(注意我现在不在我可以使用第三方日志记录解决方案的地方所以它必须像这样简单.我可以把所有这些都保留为正常std::cerr/ std::cout/ std::clog消息,如果我不得不但我更喜欢一些简单的方法,可以最大限度地减少来自多线程应用程序的日志消息交错的可能性.)
只是尝试扩展它,看看你得到了什么:
#include <iostream>
#include <sstream>
int main()
{
std::cout << "Hello World!\n";
bool val = false;
if (val)
{ std::ostringstream _s; ; _s << "No error" << std::endl; std::cerr << _s.str(); };
else
{ std::ostringstream _s; ; _s << "Error" << std::endl; std::cerr << _s.str(); };
}
Run Code Online (Sandbox Code Playgroud)
请注意{ }块是如何终止的;?
如果你需要一个宏,你应该总是这样写do { } while (0):
#define SERR(x) \
do { \
std::ostringstream _s; \
_s << (x) << std::endl; \
std::cerr << _s.str(); \
} while (0)
Run Code Online (Sandbox Code Playgroud)
这不仅解决了您的问题,而且还强制要求;在宏之后添加.否则人们可以用两种方式:
SERR("foo") // without ;
...
SERR("bar"); // with ;
Run Code Online (Sandbox Code Playgroud)