Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using std::format to create compile time objects with constexpr

Tags:

c++

c++23

std::format insists that its format string argument should be a compile time constant.

I thought this was so that std::format could be used to create compile time constant values.

However, having tried the following example, I found that the code does not compile.

#include <format>

int main() {

    constexpr auto zero = 0;
    constexpr auto my_string = std::format("{}", zero);
    return 0;
}

I attempted to compile this with

$ g++ main.cpp -std=c++23

and obtained the following error output

main.cpp: In function ‘int main()’:
main.cpp:6:43: error: call to non-‘constexpr’ function ‘std::string std::format(format_string<_Args ...>, _Args&& ...) [with _Args = {const int&}; string = __cxx11::basic_string<char>; format_string<_Args ...> = basic_format_string<char, const int&>]’
    6 |     constexpr auto my_string = std::format("{}", zero);
      |                                ~~~~~~~~~~~^~~~~~~~~~~~
In file included from main.cpp:1:
/usr/include/c++/14/format:4293:5: note: ‘std::string std::format(format_string<_Args ...>, _Args&& ...) [with _Args = {const int&}; string = __cxx11::basic_string<char>; format_string<_Args ...> = basic_format_string<char, const int&>]’ declared here
 4293 |     format(format_string<_Args...> __fmt, _Args&&... __args)

It seems as if std::format cannot be used as a constexpr after all.

Is there a solution, or a workaround, to this? Or am I simply missing something which can make this work.


Comment: As pointed out in the comments and answer, part of the reason why this isn't so is because std::string allocates its data on the heap. I guess what I am actually looking for is something which returns a const char * const, rather than strictly a std::string type. In other words, the data should be stored statically within the compiled executable.

like image 746
FreelanceConsultant Avatar asked Jan 02 '26 00:01

FreelanceConsultant


1 Answers

std::format insists that its format string argument should be a compile time constant.

I thought this was so that std::format could be used to create compile time constant values.

It is not. The motivation for std::format's format string to be a constant is to allow compile-time type checking of the format string. So that something like std::format("x={}") is a compile error, rather than a runtime error.

Is there a solution, or a workaround, to this? Or am I simply missing something which can make this work.

std::format itself is not constexpr (yet). There is no workaround.


Note also that you can still provide non-constant format strings to std::format, you just have to wrap the format string in std::runtime_format:

int main()
{
    std::print("Hello {}!\n", "world");
 
    std::string fmt;
    for (int i{}; i != 3; ++i)
    {
        fmt += "{} "; // constructs the formatting string
        std::print("{} : ", fmt);
        std::println(std::runtime_format(fmt), "alpha", 'Z', 3.14, "unused");
    }
}
like image 90
Barry Avatar answered Jan 03 '26 13:01

Barry



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!