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
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}