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());

看一看谷歌出入记录时,他们做此使用与实例化一个临时对象

LOG(INFO) << "log whatever" << 1;

和它们还具有其他有趣的宏如LOG_IF等人

考虑到你在你的代码中包含了这些地方的线条,是有可能

#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)”前缀的路线,和冲洗()其中两个它刷新到日志输出作为单个命令并添加一个新行到它。在我的实现总是这样,但你可以作出这样的条件,如果一个已不存在。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top