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

标签 c++ oop methods

我有一个 struct喜欢

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

在我的代码中我有一个 vector 并且经常这样做

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

每次我想记录一些东西时,都要有锁卫和括号似乎很冗长。起初我想也许我可以重载 <<我的结构的运算符,但我读到了它,但我认为这行不通。有什么好的方法可以将其压缩为方法调用吗?

最佳答案

您可以创建一个可变参数模板函数(例如 log_it),它采用 AN_ENUM 加上要记录的可变数量的项目,锁定 mutex一次,然后将所有内容流式传输到 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 持有:

log 0 says : i = 4.500
log 0 says : j = 4.5

我敢肯定语法可以被精炼成更漂亮的东西,但这得到了基本的想法:传递可变数量的参数,锁定在调用堆栈的顶部,然后一个一个地处理每个参数。

“日志级别”可能只是 log_it 的另一个参数。

关于c++ - 如何用方法调用替换 `{ lock_guard lock(obj.mut); obj.a_stringstream << a << b/*...*/<< n;}`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36109710/

相关文章:

C++ boost replace_all 引用

c++ - 如何删除 vector 中的最后一个和/或唯一元素?

objective-c - Objective C - 根据类型从基类创建具体类实例

c++ - 在 C++ 中对对象数组进行冒泡排序

java - NullPointerException 未引用任何对象

PHP 类 : Global variable as property in class

java - Java 中计时器的 IndexOutOfBoundsException

c++ - 编译此 C++ 代码时出错

c++ - 出现 LNK2005 和 KNK1169 错误 - 包括一个类在另一个类中

iphone - 在 iOS 5 中使用弃用的方法