gpt4 book ai didi

c++ - 包装在函数中的调试宏的惰性参数评估

转载 作者:行者123 更新时间:2023-11-30 05:15:21 25 4
gpt4 key购买 nike

我目前正在开发一个小而简单的日志记录库,作为 Boost.Log v2 的门面。 C++ 库。

我的库快完成了,我已经成功封装了Boost.Log,即:

  1. 我的库的 API 没有 Boost.Log 类型,即用户只需要处理我的类型
  2. 我的库的 ABI 没有 Boost.Log 类型,即依赖项不必链接到 Boost.Log。

还有最后一件事我目前无法解决:延迟参数评估

我将给出一个简短的使用示例,说明 Boost.Log 的行为方式:

#include <chrono>
#include <thread>

#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/trivial.hpp>

std::string time_costly_function(
const std::chrono::seconds seconds = std::chrono::seconds{1}) {
std::this_thread::sleep_for(seconds);
return "DONE with time_costly_function";
}

int main() {
boost::log::core::get()->set_filter(boost::log::trivial::severity >=
boost::log::trivial::warning);
BOOST_LOG_TRIVIAL(warning) << "This is evaluated: " << time_costly_function();
BOOST_LOG_TRIVIAL(info) << "This is NOT evaluated: "
<< time_costly_function();
}

如果运行上面的示例,您可以看到只有第一个 BOOST_LOG_TRIVIAL 的参数调用被评估,即 time_costly_function()总共只被调用一次

这正是我想要在我的库中实现的行为,但正如我所提到的,我不希望用户必须直接处理 Boost.Log,而是使用我的小型 Facade。

下面的代码说明了这个问题(非常简化以解决实际问题):

#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/trivial.hpp>

#include <chrono>
#include <thread>

std::string time_costly_function(
const std::chrono::seconds seconds = std::chrono::seconds{1}) {
std::this_thread::sleep_for(seconds);

return "DONE with time_costly_function";
}

// Encapsulates Boost.Log. The API of my logging library does not know anything
// about Boost.Log (e.g. the Pimpl idiom is used).
//
// In reality this is a member function of a class in my library with the
// following signature:
//
// void log(const SeverityLevel level, const std::string& message) override;
//
void log(const std::string& message) { BOOST_LOG_TRIVIAL(warning) << message; }

// A custom logging macro.
//
// In reality this is a macro taking the object of a class with the member
// function illustrated above:
//
// FW_LOG(logger, level, message)
//
#define FW_LOG(message) log(message)

int main() {
// TODO(wolters): This does not work, since everything is evaluated outside of
// the Boost.Log macro(s). I want to call my macro as follows.
// FW_LOG(logger, level) << message << time_costly_function();
// I.e. it should work like the Boost.Log macro(s) illustrated above.
FW_LOG("foo" + time_costly_function());
}

我在我的代码中发现了以下问题:

  1. 函数log可能不接受 std::string引用,因为那将总是导致该职能之外的评估。
  2. FW_LOG必须以支持以下语法的方式重写: FW_LOG(logger, level) << message << time_costly_function();

我考虑过使用流和/或使用模板函数进行完美转发,但我无法想出一个可行的解决方案(目前)。

要求:代码必须可以使用 MSVC 12.0、Boost.Log 1.59.0 进行编译。允许 C+11。

所以我的实际问题是:

我如何重写第二个示例中的代码(同时使用宏和函数)以获得与第一个示例中相同的行为?

最佳答案

有点像

#define FW_LOG(logger, level, message) \
do { if (logger.check_level(level)) logger.log(message); while (false)

关于c++ - 包装在函数中的调试宏的惰性参数评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43128349/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com