如何替换`{lock_guard lock(obj.mut); obj.a_stringstream<< a<< b /*...*/<< n;}`用方法调用

时间:2016-03-20 02:47:11

标签: c++ oop methods

我有struct喜欢

struct log {
    boost::mutex mut;
    std::stringstream a_stringstream;
    //...
    };

在我的代码中我有一个向量,经常做

{
    boost::lock_guard <boost::mutex> lock(logs[AN_ENUM].mut);
    logs[AN_ENUM].a_stringstream << "something" << a_double << a_string << etc;
}

每次我想要记录某些内容时,都要使用锁定装置和支架。起初我想也许我可能会为我的结构重载<<运算符,但我读到它并且我认为它不起作用。有没有一种方法可以将其压缩为方法调用?

2 个答案:

答案 0 :(得分:4)

您可以创建一个可变参数模板函数(比如log_it),它将AN_ENUM加上可变数量的项目进行记录,锁定mutex一次,然后将所有内容流式传输到{{ 1}}。例如:

a_stringstream

这不是一个庞大的代码量。 #include <mutex> #include <sstream> #include <vector> class save_stream { std::ostream& os_; char fill_; std::ios::fmtflags flags_; std::streamsize precision_; public: ~save_stream() { os_.fill(fill_); os_.flags(flags_); os_.precision(precision_); } save_stream(const save_stream&) = delete; save_stream& operator=(const save_stream&) = delete; explicit save_stream(std::ostream& os) : os_(os) , fill_(os.fill()) , flags_(os.flags()) , precision_(os.precision()) {} }; struct log { std::mutex mut; std::stringstream a_stringstream; }; std::vector<log> logs(10); enum : std::size_t {AN_ENUM}; void log_one(std::size_t) { } template <class Arg0, class ...Args> void log_one(std::size_t log, Arg0 const& arg0, Args const& ...args) { logs[log].a_stringstream << arg0; log_one(log, args...); } template <class ...Args> void log_it(std::size_t log, Args const& ...args) { std::lock_guard<std::mutex> lock(logs[log].mut); save_stream s{logs[log].a_stringstream}; logs[log].a_stringstream << "log " << log << " says : "; log_one(log, args...); logs[log].a_stringstream << '\n'; } 采用整数常量,使用它来索引log_it以锁定互斥锁,吐出前缀字符串,然后使用常量日志索引和变量数量的参数调用logs退出。

log_one然后只记录第一个参数,然后在包的其余部分递归调用log_one

可以像这样使用:

log_one

导致log_it(AN_ENUM, std::fixed, std::setprecision(3), "i = ", 4.5); log_it(AN_ENUM, "j = ", 4.5); 持有:

logs[0].a_stringstream

我确信语法可以更精细到更漂亮的东西,但是这得到了基本的想法:传递可变数量的args,锁定在调用堆栈的顶部,然后逐个处理每个arg。

“日志级别”可能只是log 0 says : i = 4.500 log 0 says : j = 4.5 的另一个参数。

答案 1 :(得分:0)

我想不出为什么这个模板重载&lt;&lt;会员不会工作:

template<typename param>
auto operator<<(param &&Param)
{
    boost::lock_guard <boost::mutex> lock(mut);

    a_stringstream << std::forward<param>(Param);

    return *this;
}

我不知道你读到的内容可能暗示这种方法不起作用,但无论你读什么,都是错的。我的例子可能需要一些调整,这里和那里,取决于你的实际类,但理论上它应该是非常可行的。