1

Is there a way to use fmt with a spec that is computed at runtime.

Noticed that with gcc 10 this code worked fine but not with modern gcc.

#include <fmt/format.h>

const char* get_spec(bool test)
{ // image this is implemented in some other .cpp file
    return test ? "->{}" : "{}<-";
}

int main() {
    const char* non_constexpr = get_spec(true);
    fmt::print(non_constexpr,1);
}

https://godbolt.org/z/oh9n3cEnT

Mikhail
  • 7,749
  • 11
  • 62
  • 136
  • Supply `->` and `<-` as strings. `fmt::print("{}{}{}", (test ? "->" : ""), 1, (test ? "" : "<-"));` – user7860670 Jun 11 '23 at 06:41
  • @user7860670 Sure but would like to get the format strings at runtime, or from some library in another translation unit. – Mikhail Jun 11 '23 at 06:42
  • Amount and types of the arguments passed are fixed at comiple-time therefore format string compatibility should be checked at compile-time as well. – user7860670 Jun 11 '23 at 06:44
  • There's a bunch of similar duplicated questions on SO. – 273K Jun 11 '23 at 06:44
  • 1
    Same issue with `std::format`, by the way... – Aconcagua Jun 11 '23 at 06:44
  • I created a wrapper that calls std::format or fmt::format and I'm not sure why I get constexpr errors. Seems silly to ask yet another question, but I can't figure out how to get this signature to work and delegate to either std::format or fmt::format. I tried assigning the format string as a constexpr before the call to pear::format and that didn't work either. https://github.com/eighty4/pear.ng/blob/osx-fmtlib/desktop/bin/pear_cli/pear_cli.cc#L38 https://github.com/eighty4/pear.ng/blob/osx-fmtlib/desktop/bin/pear_cli/format.h – adam Jun 14 '23 at 18:33

2 Answers2

3

You need to use fmt::runtime():

#include <fmt/format.h>

const char* get_spec(bool test)
{ // image this is implemented in some other .cpp file
    return test ? "->{}" : "{}<-";
}

int main() {
    const char* non_constexpr = get_spec(true);
    fmt::print(fmt::runtime(non_constexpr),1);
}

Like always, gcc has bad error descriptions. The problem is that the normal constructor for format patterns is consteval in C++20, so you cannot pass a runtime format to it.

For that purpose, just use fmt::runtime() around your runtime format pattern.

In case of C++20's std::format problem, you need to use std::vformat to resolve the problem as mentioned in cpp ref.

Afshin
  • 8,839
  • 1
  • 18
  • 53
1

You can use fmt::vprint (std::vprint_unicode in C++23) for runtime format string

const char* non_constexpr = get_spec(true);
int arg = 1;
fmt::vprint(non_constexpr, fmt::make_format_args(arg));
康桓瑋
  • 33,481
  • 5
  • 40
  • 90