c++stringc++20

How do I pass a string to use in std::format


I have been trying to pass a format string that will be used in a call to std::format and cannot find a way. Is this possible, or do I need to create a method for each expected format?

I am using clang 19.1.4 on FreeBSD 14.2 and setting -std=c++20

A simplified example:

#include <format>
#include <iostream>

using namespace std;

class mytest
{
    int m_one = 1;
    int m_two = 2;

public:
    string toString(const string& fmt) const
    {
        // this works
        // return format("{}-{}", m_one, m_two);
        // this fails
        return format(fmt, m_one, m_two);
    }
};

const string MY_FMT = "get {} and add {}";

int main(int argc, char **argv)
{
    mytest mt;

    string res = mt.toString(MY_FMT);

    cout << res << endl;

    return 0;
}

I get the following error

sample.cpp:17:23: error: call to consteval function 'std::basic_format_string<char, const int &, const int &>::basic_format_string<std::string>' is not a constant expression
   17 |         return format(fmt, m_one, m_two);
      |                       ^
sample.cpp:17:23: note: function parameter 'fmt' with unknown value cannot be used in a constant expression

Solution

  • Until C++26 you have to do this:

    return std::vformat(fmt, std::make_format_args(m_one, m_two));
    

    See this answer for a few more details. The format string in std::format must be compile-time. With C++26 you can use std::format_runtime(fmt) instead.

    But the abstraction you want is a little strange anyway. The user needs to know what the types are to build a format string, which isn't good. Suggested approach: define a formatter so that std::format("{}", mt) does the right thing. Then if you have several format styles, express them in the format mini-language, just like {:x}