1

I'm currently writing a logger for my engine and I've been stuck with a problem I could not solve. std::format takes in a constant string and a list of arguments after.

My Log functions is as follows:

template <typename... Args>
void Log(const char* message, Args&&... args)

Now in somewhere in the function scope, I try to format the string by:

std::string formattedMsg = std::format(message, args);

And I try to mess with it:

Scope<Colour::Logger> myLogger = CreateScope<Colour::Logger>("MyLogger");
myLogger->Log("Hey! I have a variable named \"a\" and it is equal to {0}", a);
myLogger->Info("Hey! I have a variable named \"a\" and it is equal to {0}", a);
myLogger->Log("Hey! I have a variable named \"a\" and it is equal to {0}", a);
myLogger->Warn("Hey! I have a variable named \"a\" and it is equal to {0}", a);
myLogger->Error("Hey! I have a variable named \"a\" and it is equal to {0}", a);
myLogger->Fatal("Hey! I have a variable named \"a\" and it is equal to {0}", a);
myLogger->Info("Hey! I have a variable named \"a\" and it is equal to {0}", a);

Scope is unique_ptr, CreateScope is make_unique. Info, Fatal, Trace etc. functions just set the level to correct one and call Log().

But that gives me the error:

std::_Basic_format_string::_Basic_format_string': call to immediate function is not a constant expression

I tried doing stuff like taking in a _Fmt_String, std::string, const char*, I tried expanding the arguments, forwarding them but none of them work. How can I format this message parameter using the args parameter using std::format?

Jarod42
  • 203,559
  • 14
  • 181
  • 302
trianglx
  • 89
  • 5
  • _"As of [P2216R3](https://wg21.link/P2216R3), it is an error if the format string is not a constant expression. [`std::vformat`](https://en.cppreference.com/w/cpp/utility/format/vformat) can be used in this case."_ – Ted Lyngmo Aug 09 '22 at 16:25
  • Doesn't work as well (and it takes in a std::wstring, I need std::string). – trianglx Aug 09 '22 at 16:25
  • I saw a very similar question a couple of days ago. – 273K Aug 09 '22 at 16:26
  • @HycroftMolmes `std::vformat` has overloads to take `std::string` too. What error do you get when using `std::vformat`? – Ted Lyngmo Aug 09 '22 at 16:27
  • Dup? https://stackoverflow.com/a/72323185/6752050 – 273K Aug 09 '22 at 16:29
  • Related to [how-to-create-a-function-that-forwards-its-arguments-to-fmtformat-keeping-the-type-safeness?](https://stackoverflow.com/questions/68675303/how-to-create-a-function-that-forwards-its-arguments-to-fmtformat-keeping-the) – Jarod42 Aug 09 '22 at 16:29
  • Dup? [Wrapping std::format in a template function fails to compile with the latest MSVC compiler update](https://stackoverflow.com/questions/72243483/wrapping-stdformat-in-a-template-function-fails-to-compile-with-the-latest-msv) – 273K Aug 09 '22 at 16:30

1 Answers1

3

This might get you started :

#include <iostream>
#include <format>

template <typename... args_t>
void Log(std::string_view fmt, args_t&&... args)
{
    std::string formatted_message = std::vformat(fmt, std::make_format_args(args...));
    std::cout << formatted_message << "\n";
}

int main()
{
    Log("Hello {0}{1}", "World", "!");
    return 0;
}
vitaut
  • 49,672
  • 25
  • 199
  • 336
Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19