0

I know the title is super confusing, but the following will make it clear.
I am using fmt library for formating and it has this precious feature.

auto res = fmt::format(FMT_STRING("{}{}"), 6, "Ed");

This is a compile time check on various things one of which is whether the number of arguments is equal to number of {} which need to be formatted.

In order not write this every time I decided to wrap this into utility:

template<typename Str, typename... Args>
auto format(Str&& str, Args&&... args)
{
    return fmt::format(FMT_STRING(std::forward<Str>(str)), std::forward<Args>(args)...);
}

And willing to use this the same way:

utils::format("{}{}",  6, "Ed");

But now I am getting this error:

constexpr variable s must be initialized by a constant expression
FMT_CONSTEXPR auto s = basic_string_view(format_str)

where s is some variable in the nested fmt::format call.

Can someone help to fix this or tell me what I am missing?


The [mcve]

template<typename Str, typename... Args>
constexpr auto format(Str&& str, Args&&... args) {
    constexpr auto&& s = std::forward<Str>(str);
}

int main () {
  format("{}{}", 6, "Ed");
}
273K
  • 29,503
  • 10
  • 41
  • 64
Eduard Rostomyan
  • 7,050
  • 2
  • 37
  • 76
  • Could you post the whole error message? What is `FMT_STRING`? I am just trying to compile your tiny pieces of code and always getting new errors. The question content w/o a [mcve] is disrespectful. – 273K Jul 31 '22 at 23:27
  • yes is a macro which than expands to wider macros – Eduard Rostomyan Jul 31 '22 at 23:35
  • The parameter of a function never has a value that is known at compile-time to be usable in a constant expression. It is therefore impossible to wrap the call to `std::format` in a function like this. The arguments must be constant expressions at the call-site. – user17732522 Jul 31 '22 at 23:56
  • The C++20/23 implementation of `std::format` uses a trick so that an explicit macro use like `FMT_STRING` is not necessary by having the first argument of `std::format` be a type that can only be constructed with a `consteval` constructor that checks the string for errors at compile-time. You could implement that yourself, but I don't think you'll be able to reuse `FMT_STRING` for the compile-time check. You would probably need to use some of the `fmt` implementation details in your `consteval` constructor. Before C++20 it is not possible to do this without a macro. – user17732522 Jul 31 '22 at 23:56
  • thanks @user17732522, is there a change you can provide a link to that C++20 trick? – Eduard Rostomyan Jul 31 '22 at 23:58
  • https://www.open-std.org/JTC1/SC22/WG21/docs/papers/2021/p2216r3.html. See also the previous versions of the paper (replace the number after `r` and potentially the `2021` with `2020`). According to the paper it is/was also intended that this becomes the default behavior for `{fmt}`. – user17732522 Aug 01 '22 at 00:02
  • `{fmt}` behaves the same way by-default since version 8.0.0 if compiled with a C++20-enabled compiler, see https://github.com/fmtlib/fmt/blob/master/ChangeLog.rst#800---2021-06-21. So just upgrade and you'll don't need to do anything. – user17732522 Aug 01 '22 at 00:07

0 Answers0