【发布时间】:2021-09-07 12:02:11
【问题描述】:
我有一个类,它在其构造函数中采用一组 C printf 可变参数,如下所示:
class Foo {
public:
Foo(const char* str, ...) __attribute__((format(printf, 2, 3)));
现在我希望能够在此类中使用fmt library。如果我愿意改变所有来电者,我可以像这样切换它:
class Foo {
public:
template<typename Str, typename... Args>
Foo(const Str& str, const Args&... args)
: Foo(str, fmt::make_args_checked<Args...>(str, args...))
{}
private:
Foo(fmt::string_view fmt, fmt::format_args args);
但是这个类在 100 多个地方使用,“改变世界”是不可行的。所以我想保留这两个构造函数,但显然现在我需要一种方法来在它们之间进行选择。我对必须添加新的虚拟参数或其他东西并不感到兴奋。
然后我想,好吧,我也很想强制使用FMT_STRING() 宏,因为我的 printf 样式代码利用了 GCC 和 clang 中的 printf 格式检查。所以也许我可以用它做点什么:我可以创建自己的宏,比如MYFMT(),它会以某种方式调用 FMT_STRING(),或者至少做同样的检查,然后解析为我自己的类型,可以用来选择不同的构造函数;类似:
#define MYFMT(_f) ...
class Foo {
public:
Foo(const char* str, ...);
Foo(const MyType& str, ...) ...
所以,用法是这样的:
auto x = Foo("this is a %s string", "printf");
auto y = Foo(MYFMT("this is a {} string"), "fmt");
但我已经玩了几个小时,并试图围绕 FMT_STRING 宏的工作原理以及我需要做什么,但我什么也想不出来。也许由于某种原因这是不可能的,但如果有人有任何提示,那就太好了。
FWIW 我的基础编译器是 GCC 10、clang 9 和 MSVC 2019,所以我至少可以依赖 C++17。
【问题讨论】: