c++ - 保持函数参数的 consteval-ness

标签 c++ c++20 constexpr fmt consteval

我正在使用整洁的 fmt 库,在其版本 8 中,如果编译器支持相关功能,则会对其格式字符串进行编译时检查。

在某个时候,我想编写以下代码:

throw my_exception("error: {}", 123);

可悲的是,幼稚的实现:

struct my_exception : std::runtime_error {
  template<typename... Args>
  my_exception(Args&&... args)
    : std::runtime_error{fmt::format(std::forward<Args>(args)...)} 
  { }
};

失败,因为这失去了字符串文字参数的“consteval-ness”,这是 fmt::format 所要求的。 目前,我选择了以下内容:

template<std::size_t N>
struct literal {
  constexpr literal(const char (&str)[N]) noexcept {
    std::copy_n(str, N, this->str);
  }

  char str[N];
};

template<literal lit>
struct exception : std::runtime_error {
  template<typename... Args>
  exception(Args&&... args)
    : std::runtime_error{fmt::format(lit.str, std::forward<Args>(args)...)}
  {

  }
};

它被称为

throw my_exception<"foo {}">(123);

如何在保持编译时检查的同时恢复正常的函数调用语法?

最佳答案

在 {fmt} 8.0 及更高版本中,您可以使用 format_string 模板来执行此操作,顾名思义,该模板表示格式字符串 (https://godbolt.org/z/bqvvMMnjG):

struct my_exception : std::runtime_error {
  template <typename... T>
  my_exception(fmt::format_string<T...> fmt, T&&... args)
    : std::runtime_error(fmt::format(fmt, std::forward<T>(args)...)) {}
};

关于c++ - 保持函数参数的 consteval-ness,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69596108/

相关文章:

c++ - 为什么在删除一个函数时,在函数参数中使用指定初始值设定项的这段代码从不明确变为不编译?

c++ - GNU const/纯属性与 constexpr

c++ - 在常数值上强制 Clang 为 "perform math early"

c++ - 有关闭多个句柄的简单方法吗?

c++ - 生成使用非默认 <=> 的 == 运算符

c++ - 理解 C++ 中显式构造函数的问题

需要以 OutputIterator 作为参数的成员函数的 C++ 概念

c++ - constexpr 是否暗示 noexcept?

c++ - 调用 pthread_create() 时出现段错误 C++ Linux

c++ - 绑定(bind)到枚举的类成员