I am writing a function that for the purpose of this question is similar to std::format
, in that std::format("{}")
fails at compile-time, while std::format("{}", 1)
compiles.
I want to make sure that no user calling my function can accidentally write std::format("{}")
; instead, I want this to be a compile-time error, and this is the current behavior.
How do I ensure this behavior does not regress?
I have tried the following approach:
#include <format>
template<class T>
concept FormatMissingArgumentCompiles = requires { std::format("{}"); };
// This check incorrectly states that 'Format missing argument compiles'
static_assert(!FormatMissingArgumentCompiles<void>, "Format missing argument compiles");
int main() {}
However, it seems that std::format("{}")
is a well-formed expression unless evaluated, and requires
does not evaluate its arguments (https://en.cppreference.com/w/cpp/language/expressions.html#Potentially-evaluated_expressions).
Can I make requires
evaluate (at least partially) its std::format_string
arguments as it would at compile time of regular code to see that construction of std::format("{}")
is ill-formed?
Update: three comments and an answer indicate to me that my question wasn't super clear. I am not looking for a way to make compilation fail if the user writes std::format("{}")
- I have that. I want compilation to fail if writing std::format("{}")
would not make compilation fail.
Not sure it is what you want, but, you can use template class to force constexpr
evaluation. std::format_string
is the class with consteval
constructor to evaluate:
template<class... Ts>
concept FormatMissingArgumentCompiles = requires {
std::array<int, (std::format_string<Ts...>("{}"), 42)>{};
};
static_assert(!FormatMissingArgumentCompiles<>, "Format missing argument compiles");
static_assert(FormatMissingArgumentCompiles<int>);
static_assert(FormatMissingArgumentCompiles<int, int>); // std::format("{}", 1, 2) is valid