首页 > 解决方案 > 当其中一个是函数参数时,在编译时连接 const char

问题描述

我正在尝试为 spdlog 中的每个日志字符串添加一个文件名前缀。Spdlog 格式化字符串如下所示:

Test log {}

日志是这样写的: spdlog::error("Test log {}", value)

我试图在格式化字符串之前包装这个调用并连接额外的 {},所以我可以在那里传递文件的前缀。

static constexpr char * prefixHolder("{} ");

template<typename... Args>
void critical(const char fmt[], Args&&... args) const
{
    constexpr auto fullFmt = prefixHolder + fmt; //I can't find any solution for this

    spdlog::critical(fullFmt, m_prefix, std::forward<Args>(args)...);
}


Log log("MyClassOrLogger");

log.critical("My format {}", value);

是否可以在编译时解决这个问题?我尝试了一些方法,但我还没有找到任何方法来为编译器制作输入 fmt 参数 constexpr。

C++ 17

有什么建议或解决方案吗?

谢谢

标签: c++c++17constexpr

解决方案


参数值不能用于 constexpr。

你可能会转:

template<typename... Args>
constexpr void critical(const char fmt[], Args&&... args)

进入

template <char... cs, typename... Args>
void critical(std::integer_sequence<char, cs...>, Args&&... args)
{
    constexpr char fullFmt[] = {'{', '}', ' ', cs... , '\0'};

    spdlog::critical(fullFmt, m_prefix, std::forward<Args>(args)...);
}

允许拥有 constexpr char 数组。

ensure-that-c​​har-pointers-always-point-to-the-same-string-literal显示了从文字字符串创建类似序列的方法。在您的情况下,它将是:

template <typename Char, Char... Cs>
constexpr auto operator"" _cs() -> std::integer_sequence<Char, Cs...> {
    return {};
}

用法是这样的:

log.critical("My format {}"_cs, value); // gcc extension
log.critical(MAKE_SEQUENCE("My format {}"), value);

带有 gcc 扩展的演示。使用 MACRO 进行
演示。


推荐阅读