[libcxx-commits] [PATCH] D113137: [libc++] Fix lifetime issues of temporaries.

Mark de Wever via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Thu Nov 4 10:57:34 PDT 2021


Mordante added inline comments.


================
Comment at: libcxx/test/std/utilities/format/format.formatter/format.context/format.context/ctor.pass.cpp:54
+  auto format_arg_store = std::make_format_args<std::basic_format_context<OutIt, CharT>>(true, CharT('a'), 42, string);
+  std::basic_format_args args{format_arg_store};
 
----------------
Quuxplusone wrote:
> Style: `std::basic_format_args args = format_arg_store;` (it's not an aggregate or sequence-container)
> 
> Do I understand correctly that `std::make_format_args` does not actually return a `std::format_args`? Who came up with that? 😛 
> 
> But does this fix the dangling? https://en.cppreference.com/w/cpp/utility/format/make_format_args insists that "A formatting argument has reference semantics for user-defined types and does not extend the lifetime of `args`," so do you really need to do something like
> ```
> auto args_tuple = std::make_tuple(true, CharT('a'), 42, string);
> auto args = std::apply([](auto&&... ts) {
>     return std::make_format_args<std::basic_format_context<OutIt, CharT>>(static_cast<decltype(ts)>(ts)...);
> }, std::tuple<bool&&, CharT&&, int&&, std::basic_string<CharT>&>(args_tuple));
> ```
> ? (Or consider turning each of the following blocks into its own function, and just calling them like `test_foo(std::make_format_args<...>(...));` which would eliminate the lifetime issues in a more realistic way: basically by treating `format_args` as a parameter-only type.)
> Style: `std::basic_format_args args = format_arg_store;` (it's not an aggregate or sequence-container)
> 
> Do I understand correctly that `std::make_format_args` does not actually return a `std::format_args`? Who came up with that? 😛 

Indeed
```
Returns an object that stores an array of formatting arguments and can be implicitly converted to std::basic_format_args<Context>. 
```
The `basic_format_args` stores a pointer to the data of this array. Before the change that array was a temporary, after the change it's no longer a temporary. (The format functions are implemented like `return vformat_to(out, fmt.str, make_format_args(args...));`. So the temporary's lifetime isn't an issue there.)

> But does this fix the dangling? https://en.cppreference.com/w/cpp/utility/format/make_format_args insists that "A formatting argument has reference semantics for user-defined types and does not extend the lifetime of `args`," so do you really need to do something like
> ```
> auto args_tuple = std::make_tuple(true, CharT('a'), 42, string);
> auto args = std::apply([](auto&&... ts) {
>     return std::make_format_args<std::basic_format_context<OutIt, CharT>>(static_cast<decltype(ts)>(ts)...);
> }, std::tuple<bool&&, CharT&&, int&&, std::basic_string<CharT>&>(args_tuple));
> ```
> ? (Or consider turning each of the following blocks into its own function, and just calling them like `test_foo(std::make_format_args<...>(...));` which would eliminate the lifetime issues in a more realistic way: basically by treating `format_args` as a parameter-only type.)

No this should work; the values of the fundamental types are copied in the array so they won't dangle. The emphasis in the note is `user-defined types`. Using a temporary would be an issue for `std::string`, it's stored as a `std::string_view` in the array. That's why the argument `string` isn't a temporary.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D113137/new/

https://reviews.llvm.org/D113137



More information about the libcxx-commits mailing list