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?

7
  • "As of P2216R3, it is an error if the format string is not a constant expression. std::vformat can be used in this case." Commented Aug 9, 2022 at 16:25
  • Doesn't work as well (and it takes in a std::wstring, I need std::string). Commented Aug 9, 2022 at 16:25
  • I saw a very similar question a couple of days ago. Commented Aug 9, 2022 at 16:26
  • @HycroftMolmes std::vformat has overloads to take std::string too. What error do you get when using std::vformat? Commented Aug 9, 2022 at 16:27
  • Dup? stackoverflow.com/a/72323185/6752050 Commented Aug 9, 2022 at 16:29

1 Answer 1

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;
}
Sign up to request clarification or add additional context in comments.

3 Comments

Wow, I didn't know I had to use make_format_args.
Arguments to make_format_args shouldn't be forwarded, see e.g. eel.is/c++draft/format#functions-2
@vitaut the std::forward has become a bit of an automatism with me when using &&. So thank you for this fix.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.