编译时:基于其中一个字符串实参调用函数



我试图创建一个函数,部分字面量和部分非字面量可变参数返回bool值,并基于结果,我必须用相同的参数和顺序转发所有.

示例1:

int x = some_runtime_func(); // evaluated to 20
float y = some_runtime_func(); // evaluated to 10.5
MY_PRINT("{} {}", x, y); // prints 20 10.5
MY_PRINT("%d" %f", x, y); // prints 20 10.5

注意MY_PRINT是一个MACRO函数,它将与__VA_ARGS__

一起传递为了实现这一点,我将解析和检查字符串,并根据其内容将其转发给fmt库函数。

我设想的底层函数是这样的(由于__VA_ARGS__崩溃而没有变量命名更改)

bool is_valid = my_formatter_checker("{} {}", x, y);
if constexpr(is_valid)
{
fmt::print("{} {}", x, y);
}
else
{
fmt::printf("{} {}", x, y);
}

虽然x和y不是编译时间字面值,但该字符串是编译时间字面值,我想决定是否只根据字符串字面值使用特定的函数。所以在这个例子中,函数内部甚至没有使用参数x,我只使用了第一个参数

为了简单起见,如果字符串不是编译时字符串,那么我将强制它在运行时对其求值。const char* vs const char[N],我相信可以通过模板类型特征来实现。

此外,fmt允许第一个参数是一个特定的目标,如stdoutstderr或file。在这种情况下,第一个参数可以是另一种类型,而不是字符串字面值。

示例2:

int x = runtime_function(); // returns 20
MY_PRINT(stderr, "{}", x); // prints 20 to stderr
MY_PRINT(stderr, "%d", x); // prints 20 to stderr

对于本例,我使用MY_PRINT的第二个参数,因为第二个参数是字符串字面值。

主要问题是如何创建函数my_formatter_checker,它同时接受constexpr参数和非constexpr参数,只解析第一个字符串参数。我从函数端更改调用,这样函数的用户就不必添加额外的宏或调用。我希望这个函数可以用模板元编程或constexpr函数来实现,因为如果参数不是字符串字面值,它可以在运行时求值。

这样做的一种方法是使用带有隐式consteval构造函数的类。这就是{fmt}为编译时格式字符串检查所做的工作。

例如:

struct format_string {
bool is_valid;
const char* str;
consteval format_string(const char* s) : str(s) {
// Implement your compile-time logic here.
is_valid = *s == '{';
}
};
template <typename... T>
std::string my_print(format_string s, T&&... args) {
if (s.is_valid)
fmt::print(fmt::runtime(s.str), std::forward<T>(args)...);
}

要做到这一点,你需要重构你的代码,把所有的编译时逻辑放在format_string的构造函数中,而运行时逻辑放在my_print函数中。

https://godbolt.org/z/7qonoPqWr

相关内容

最新更新