std::format_args

It is my understanding that std::format_args requires compile-time stated arguments. Is it possible to generate a std::format_args variable in some way at run-time for use with std::vformat? I don't think so but could someone confirm please. No specific requirement as we're currently just having 'a play' with this....


Types are known at compile time; values may be known only at run-time.

For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <string_view>
#include <string>
#include <format>

struct rectangle { int height = 1 ; int width = 1 ; };

template <> struct std::formatter<rectangle> : std::formatter<std::string_view>
{
    // uses inherited parse() from std::formatter<std::string_view>

    template < typename FORMAT_CONTEXT > // customise format() for rectangle
    auto format( const rectangle& r, FORMAT_CONTEXT& context )
    { return std::formatter<string_view>::format( std::format( "rect[{}x{}]", r.height, r.width ), context ); }
};

int main()
{
    rectangle rect1 { 20, 30 }, rect2 { 444444, 555555 } ;

    std::cout << "rect1 height and width? " && std::cin >> rect1.height >> rect1.width ;

    // specify width and fill at run-time
    int width = 30 ;
    char fill = '.' ;
    std::cout << "format width and fill? " && std::cin >> width >> fill ;

    const std::string fmt = std::string("{:") + fill + '^' + std::to_string(width) + '}' ;
    const std::string fmt_sring = fmt + "  and  " + fmt ;
    auto fmt_args = std::make_format_args( rect1, rect2 ) ; // holder of type-erased formatting args

    // print two rectangle objects, each centred in a field of width width, with the fill character as fill
    std::cout << '"' << std::vformat( fmt_sring, fmt_args ) << "\"\n" ;
}

Thanks for that example. But consider:

1
2
3
4
5
6
int main() {
	auto args { std::make_format_args( 1, 3.4, "foobar" ) };    // Compile time OK

	//args.insert(78);	// At runtime

}


L2 is OK. But I was talking about L4 where args are added to at run-time as opposed to compile time. I don't think this can done in any way...


Last edited on
Arguments can't be added to or removed from objects of type std::basic_format_args<> or to the unspecified object returned by std::make_format_args(), even at compile-time.

Since format arguments have reference semantics for non-scalar types, we could write a custom formatter for a modifiable range and add then add items to the range from outside.
Or if there is no immediate requirement, wait for C++23's __cpp_lib_format_ranges to become available.
Last edited on
Thanks. That's what I thought. This topic came up in conversations over a 'few' drinks in the pub...
Topic archived. No new replies allowed.