我正在尝试创建一个自定义错误类,其构造函数通过将参数传递给 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/