I am trying to create a function with partial literals and partial non-literals variadic arguments that return a bool and based on the result, I have to forward all with the same arguments and order .
Example 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
Note that MY_PRINT is a MACRO function that will pass with __VA_ARGS__
To achieve this, I will parse and check the string and forwards it to fmt
library functions based on its content.
The underlying function that I envision is something like this (without variable naming change due to __VA_ARGS__
collapse)
bool is_valid = my_formatter_checker("{} {}", x, y);
if constexpr(is_valid)
{
fmt::print("{} {}", x, y);
}
else
{
fmt::printf("{} {}", x, y);
}
While the x and y are not compiled time literals, the string is a compiled time literals , and I want to decide whether I use a specific function only based on the string literals. So for this example, the parameter x is not even used inside the function, and I only use the first argument
And to make it simple, If the string is not a compile-time string, then I will force it to evaluate it at runtime. const char* vs const char[N]
which I believe can be implemented with templates type traits.
In addition, fmt allows the first argument to be a specific target such as stdout
or stderr
or file. which is a case where the first argument can be another type that is not a string literals.
Example 2:
int x = runtime_function(); // returns 20
MY_PRINT(stderr, "{}", x); // prints 20 to stderr
MY_PRINT(stderr, "%d", x); // prints 20 to stderr
For this case, I am using the second argument to the MY_PRINT
since the second argument is the string literals.
The main question is how to create the function my_formatter_checker
that takes in both a constexpr parameter and non constexpr parameter, parse only the first string argument. I cannot change the call from the function side such that the user of the function does not have to add additional macro or calls. I expect that this function can be implemented preferably with template metaprogramming or constexpr functions since if the argument is not a string literal it can be evaluated at runtime.
One way of doing this is using a class with an implicit consteval
constructor. This is what {fmt} does for compile-time format string checks.
For example:
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)...);
}
For this to work you need to restructure your code to place all the compile-time logic in format_string
's constructor and the runtime logic is in the my_print
function.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.