反正是有写以下为C ++宏?
-
25-09-2019 - |
题
my_macro << 1 << "hello world" << blah->getValue() << std::endl;
应扩展为:
std::ostringstream oss;
oss << 1 << "hello world" << blah->getValue() << std::endl;
ThreadSafeLogging(oss.str());
解决方案
#define my_macro my_stream()
class my_stream: public std::ostringstream {
public:
my_stream() {}
~my_stream() {
ThreadSafeLogging(this->str());
}
};
int main() {
my_macro << 1 << "hello world" << std::endl;
}
一个临时类型my_stream
的被创建,它是ostringstream
的子类。所有操作到临时工作,因为他们将在一个ostringstream
。
当该语句结束时,临时对象超出的范围出并被破坏(即在main()对整个打印操作中分号后右)。所述my_stream
析构函数调用ThreadSafeLogging
用“收集”先前的数据。
测试(克++)。
感谢/信用野狗以指出如何简化整个事情,所以我不需要重载operator<<
。太差upvotes不能共享。
其他提示
你不能只是从ostream的派生,并提供自己的线程安全的实现?然后,你可以只是做
myCOutObject << 1 << "hello world" << blah->getValue() << std::endl;
和得到无宏完全相同的功能,并使用C ++正确?
没有。问题是,不使用函数的语法,宏仅限于被替换它在哪里。
不过,你要是愿意使用函数的语法,就可以既之前和之后ARGS替换的东西。
my_macro(1 << "hello world" << blah->getValue() << std::endl);
您可通过界定MyMacro为:
#define my_macro(args) std::ostreamstring oss; \
oss << args; \
ThreadSafeLogging(oss.str());
考虑到你在你的代码中包含了这些地方的线条,是有可能
#include <iostream>
#include <sstream>
__LINE__
宏由所有非标准编译器定义。
因此,我们可以用它来生成一个变量名至极不同的是每次使用宏:)
下面是被看作是仅一语句指令的新版本: (编辑)的
#define Var_(Name, Index) Name##Index
#define Var(Name, Index) Var_(Name, Index)
#define my_macro \
for (struct { int x; std::ostringstream oss; } Var(s, __LINE__) = { 0 }; \
Var(s, __LINE__).x<2; ++Var(s, __LINE__).x) \
if (Var(s, __LINE__).x==1) ThreadSafeLogging(Var(s, __LINE__).oss.str()); \
else Var(s, __LINE__).oss
// So you can use it like this
int main()
{
if (4 != 2)
my_macro << 4 << " hello " << std::endl;
my_macro << 2 << " world !" << std::endl;
}
Developper可能不会需要在同一行两次使用该宏becasue操作者<<
的简单性。但是,在你需要这种情况下,您可以切换通过__LINE__
使用__COUNTER__
(这是非标准!)。由于Quuxplusone此尖端
下面是另一个很下流的手段,我看到别的地方。它比我其他的答案有显著的缺点:两次在相同的范围,因为它声明一个变量,你不能使用它。但是,它可能仍然是有趣的其他的,你想拥有somemacro foo
运行一些案件的之后的foo
。
#define my_macro \
std::ostringstream oss; \
for (int x=0; x<2; ++x) \
if (x==1) ThreadSafeLogging(oss.str()); \
else oss
int main() {
my_macro << 1 << "hello world" << std::endl;
}
在记录设置我有也非常相似:
bool ShouldLog(const char* file, size_t line, Priority prio);
class LoggerOutput : public std::stringstream {
public:
LoggerOutput(const char* file, size_t line, Priority prio)
: prio(prio)
{
Prefix(file, line, prio);
}
void Prefix(const char* file, size_t line, Priority prio);
~LoggerOutput() {
Flush();
}
void Flush();
private:
Priority prio;
};
#define LOG(Prio) if (!Logging::ShouldLog(__FILE__, __LINE__, Prio)) {} else Logging::LoggerOutput(__FILE__, __LINE__, Prio)
如果你的日志被禁用,从未创建ostream的和小的开销存在。您可以对文件名和行号(S)或优先级配置日志记录。该ShouldLog函数可以调用之间改变,所以你可以节制或限制输出。日志输出使用两个函数来修改本身,前缀,增加了一个“文件:行:(PRIO)”前缀的路线,和冲洗()其中两个它刷新到日志输出作为单个命令并添加一个新行到它。在我的实现总是这样,但你可以作出这样的条件,如果一个已不存在。