c++ - {fmt} : always compile-time check format string in function

标签 c++ constexpr compile-time fmt

我正在尝试创建一个自定义错误类,其构造函数通过将参数传递给 fmt::format() 来创建错误消息。我希望它始终在编译时根据参数检查格式字符串,而不必每次抛出时都显式使用 FMT_STRING()。像这样的东西:

class Err : public std::exception 
{
private:
    std::string m_text;
public: 
    template <typename S, typename... Args>
    Err(const S& format, Args&&... args) {
        m_text = fmt::format(FMT_STRING(format), args...);
    }
    
    virtual const char* what() const noexcept {return m_text.c_str();}
};

// ------------------------ 

throw Err("Error {:d}", 10);     // works
throw Err("Error {:d}", "abc");  // cause Compile-time error

使用前面的代码,我在 FMT_STRING() 宏上遇到错误:

error C2326: 'Err::{ctor}::<lambda_1>::()::FMT_COMPILE_STRING::operator fmt::v7::basic_string_view<char>(void) const': function cannot access 'format' 
message : see reference to function template instantiation 'Err::Err<char[11],int>(const S (&),int &&)' being compiled with [ S=char [11] ]

我对模板编程的经验很少。如何使它始终在编译时检查格式字符串,而无需每次都显式使用 FMT_STRING()

最佳答案

您可以在 C++20 和最新版本的 {fmt} 中执行此类编译时检查,如下所示:

#include <fmt/core.h>

class Err : public std::exception {
 private:
  std::string m_text;

 public: 
  template <typename... T>
  Err(fmt::format_string<T...> format_str, T&&... args) {
    m_text = fmt::format(format_str, std::forward<T>(args)...);
  }

  virtual const char* what() const noexcept { return m_text.c_str(); }
};

// ------------------------ 

throw Err("Error {:d}", 10);     // works
throw Err("Error {:d}", "abc");  // compile-time error

Godbolt 演示:https://godbolt.org/z/ceGznTaEh

关于c++ - {fmt} : always compile-time check format string in function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67076274/

相关文章:

c++访问对象 vector 中对象的元素

c++ - 如何在 Qt - Visual Studio 2013 项目中设置单元测试

c++ - C++ 中的 constexpr 指针和内存管理

c++ - 如何在编译时检查两种类型是否相同(如果它与 Boost strong typedef 一起使用则加分)

c++ - 虚拟 constexpr 协变返回类型

c++ - wxWidgets 在编译时包含图像

c - 嵌套 {} 内局部变量的内存分配

c++ - 为什么要在 lambdas 中捕获 this 以及指向 this 的共享指针?

c++ - OpenGL在角落绘制轴

c++ - if constexpr 似乎只有在两种情况都有效的情况下才有效