我有一些专有记录器的代码:
#define LOG GetStream()
GetStream返回std :: ostream的位置。用户会这样做:
LOG << "text";
我需要这是线程安全的,但我想避免这种情况:
#define END Unlock();
#define LOG Lock(); GetStream() << "text" << END;
由于用户需要添加&#34; END&#34;:
LOG << "Text" << END;
有什么想法吗?
备注:我使用this之类的东西处理回车。
答案 0 :(得分:2)
解决此问题的一种方法是使用函数式宏,在这里使用C ++块和范围包含锁定/解锁:
#define LOG(output) \
do \
{ \
LockingClass lock; \
GetStream() << output; \
} while (0)
LockingClass
(或者你想要命名的任何东西)是一个范围锁,它在构造时锁定流,并在销毁时将其解锁。
可以像例如一样使用。
LOG("hello variable is " << variable);
不能将它与包含逗号的表达式一起使用,但预处理器会将逗号解释为宏的参数分隔符。可能可以用variadic macros来解决。
答案 1 :(得分:1)
尽管如此:
#define LOG for (int i = 0 ;i < 1 ;i++,(i == 1 ? Unlock())) LockAndGetStream()
答案 2 :(得分:0)
TL; TD:你不能只让宏x<<text<<end
工作。
为了将带有分号(;
)的许多表达式与宏放在一起,唯一有效的方法是使用do{..} while(0)
语句,您可以在此处阅读更多内容:do { ... } while (0) — what is it good for?
现在,除非您想使用<<
之类的某些运算符,否则您无法使用do{..} while(0)
costruct。
我的建议:将std::ostream
包装在重载<<
运算符的类中。在重载内,请致电Lock
和Unlock
。
struct MyLogger{
std::ostream& operator << (Text text){
Lock();
stream <<text;
Unlock();
return stream;
}
}
其中stream
是您将文本流式传输到的流。
现在,您可以从此类创建一个对象并使用常规的非宏<<
:
NyLogger Log;
Log << text;