C++ 捕获可变参数模板参数中所有指针包装器的值

C++ capture value of all pointer wrappers in variadic template arguments

std::deque<std::function<std::string()>> log_queue;

void store_log(T&& t, U&&... u) const
{
    log_queue.push_back(
        [t, u...]() {
            return format_log(t, u...));
        });
    
    if (log_queue.size() > 1000)
    {
        log_queue.pop_front();
    }
}

我使用上述函数将最新的 1000 条日志消息存储在循环缓冲区中,并在我的开发环境出现问题时打印 log_queue 的内容。

这种方法有问题。一些参数 (U...) 是 pointer wrappers。 因此,当我打印 log_queue 内容时,我看到这些指针的 最后更新值 而不是调用 store_log 函数时的值。我可以通过存储 std::string 而不是 lambda 来解决这个问题,但这非常昂贵(我只想对最后 1000 条日志进行字符串化)。所以我想存储指针包装器包含的值 而不是指针包装器本身。有什么简单的方法吗?

指针包装详细信息:

template <typename T>
class ptr_wrapper
{
    T* t = nullptr;
    int ref_count = 0; 
    // constructors and destructors
    // functions for updating ref_count whenevr this object is copies/moved etc
};

};

您可以在捕获之前应用转换:

void store_log(T&& t, Us&&... us) const
{
    log_queue.push_back(
        [tup = std::make_tuple(value(t), value(us)...)]() {
            return std::apply([](const auto&... args){ format_log(args...), tup));
        });
    
    if (log_queue.size() > 1000)
    {
        log_queue.pop_front();
    }
}

template <typename T>
const T& value(const T& value) { return value; }

template <typename T>
std::optional<T> value(const ptr_wrapper<T>& wrapper) {
    if (wrapper.t) return *wrapper.t;
    return {};
}

// other overloads possible to do deep copy, instead of keeping reference
// ...

C++14的语法;在 C++11 中,您必须在 lambda 之前声明变量。