Difference between revisions of "cpp/utility/format/make format args"
D41D8CD98F (Talk | contribs) m (→Returns) |
|||
Line 18: | Line 18: | ||
Returns an object that stores an array of formatting arguments and can be implicitly converted to {{lc|std::basic_format_args|std::basic_format_args<Context>}}. | Returns an object that stores an array of formatting arguments and can be implicitly converted to {{lc|std::basic_format_args|std::basic_format_args<Context>}}. | ||
− | The behavior is undefined if {{c|typename Context::template formatter_type<Ti>}} does not meet the {{named req|BasicFormatter}} requirements for any {{tt|Ti}} in {{tt|Args}}. | + | The behavior is undefined if {{c|typename Context::template formatter_type<std::remove_cvref_t<Ti>>}} does not meet the {{named req|BasicFormatter}} requirements for any {{tt|Ti}} in {{tt|Args}}. |
+ | |||
+ | The program is ill-formed if a {{c|std::basic_format_arg<Context>::handle}} is needed to be stored (see below) and neither {{tt|TD}} nor {{c|const TD}} satisfies {{ltt|cpp/utility/format/formattable|''formattable-with''}}. | ||
===Parameters=== | ===Parameters=== | ||
Line 39: | Line 41: | ||
* otherwise, if {{c|std::decay_t<TD>}} is {{c|Context::char_type*}} or {{c|const Context::char_type*}}, the {{lc|std::basic_format_arg}} stores {{c|static_cast<const Context::char_type*>(t)}}; | * otherwise, if {{c|std::decay_t<TD>}} is {{c|Context::char_type*}} or {{c|const Context::char_type*}}, the {{lc|std::basic_format_arg}} stores {{c|static_cast<const Context::char_type*>(t)}}; | ||
* otherwise, if {{c|std::is_void_v<std::remove_pointer_t<TD>>}} is {{c|true}} or {{c|std::is_null_pointer_v<TD>}} is {{c|true}}, the {{lc|std::basic_format_arg}} stores {{c|static_cast<const void*>(t)}}; | * otherwise, if {{c|std::is_void_v<std::remove_pointer_t<TD>>}} is {{c|true}} or {{c|std::is_null_pointer_v<TD>}} is {{c|true}}, the {{lc|std::basic_format_arg}} stores {{c|static_cast<const void*>(t)}}; | ||
− | * otherwise, the {{lc|std::basic_format_arg}} stores {{c|std::basic_format_arg<Context>::handle | + | * otherwise, the {{lc|std::basic_format_arg}} stores a {{c|std::basic_format_arg<Context>::handle}} that stores a pointer to {{tt|t}} and a function pointer to a function that performs the operations needed for {{rlpt|basic_format_arg/handle|handle::format()}}. |
===Notes=== | ===Notes=== | ||
Line 89: | Line 91: | ||
{{dr list begin}} | {{dr list begin}} | ||
{{dr list item|paper=P2418R2|std=C++20|before=objects that are neither const-usable nor copyable<br>(such as generator-like objects) are not formattable|after=allow formatting these objects}} | {{dr list item|paper=P2418R2|std=C++20|before=objects that are neither const-usable nor copyable<br>(such as generator-like objects) are not formattable|after=allow formatting these objects}} | ||
+ | {{dr list item|wg=lwg|dr=3631|std=c++20|before=cv-qualified arguments were incorrectly handled after P2418R2|after=handling corrected}} | ||
{{dr list end}} | {{dr list end}} | ||
Revision as of 00:49, 6 September 2023
Defined in header <format>
|
||
template< class Context = std::format_context, class... Args > /*format-arg-store*/<Context, Args...> |
(1) | (since C++20) |
template< class... Args > /*format-arg-store*/<std::wformat_context, Args...> |
(2) | (since C++20) |
Returns an object that stores an array of formatting arguments and can be implicitly converted to std::basic_format_args<Context>.
The behavior is undefined if typename Context::template formatter_type<std::remove_cvref_t<Ti>> does not meet the BasicFormatter requirements for any Ti
in Args
.
The program is ill-formed if a std::basic_format_arg<Context>::handle is needed to be stored (see below) and neither TD
nor const TD satisfies formattable-with.
Contents |
Parameters
args... | - | values to be used as formatting arguments |
Returns
An object that holds the formatting arguments.
For each argument t
of type T
, let TD
be std::remove_const_t<std::remove_reference_t<T>>. The corresponding std::basic_format_arg value obtained from the result (after converting to std::basic_format_args) is determined as below:
- if
TD
is bool orContext::char_type
, the std::basic_format_arg stores t; - otherwise, if
TD
is char andContext::char_type
is wchar_t, the std::basic_format_arg stores static_cast<wchar_t>(t); - otherwise, if
TD
is a signed integer type whose size is not greater than int, the std::basic_format_arg stores static_cast<int>(t); - otherwise, if
TD
is a unsigned integer type whose size is not greater than unsigned int, the std::basic_format_arg stores static_cast<unsigned int>(t); - otherwise, if
TD
is a signed integer type whose size is not greater than long long, the std::basic_format_arg stores static_cast<long long>(t); - otherwise, if
TD
is a unsigned integer type whose size is not greater than unsigned long long, the std::basic_format_arg stores static_cast<unsigned long long>(t); - otherwise, if
TD
is float, double, or long double, the std::basic_format_arg stores t; - otherwise, if
TD
is a std::basic_string_view or std::basic_string specialization andTD::char_type
isContext::char_type
, the std::basic_format_arg stores std::basic_string_view<Context::char_type>(t.data(), t.size()); - otherwise, if std::decay_t<TD> is Context::char_type* or const Context::char_type*, the std::basic_format_arg stores static_cast<const Context::char_type*>(t);
- otherwise, if std::is_void_v<std::remove_pointer_t<TD>> is true or std::is_null_pointer_v<TD> is true, the std::basic_format_arg stores static_cast<const void*>(t);
- otherwise, the std::basic_format_arg stores a std::basic_format_arg<Context>::handle that stores a pointer to
t
and a function pointer to a function that performs the operations needed forhandle::format()
.
Notes
A formatting argument has reference semantics for user-defined types and does not extend the lifetime of args
. It is the programmer's responsibility to ensure that args
outlive the return value. Usually, the result is only used as argument to formatting function.
Example
#include <array> #include <format> #include <iostream> #include <string_view> void raw_write_to_log(std::string_view users_fmt, std::format_args&& args) { static int n{}; std::clog << std::format("{:04} : ", n++) << std::vformat(users_fmt, args) << '\n'; } template <typename... Args> constexpr void log(Args&&... args) { // Generate formatting string "{} "... std::array<char, sizeof...(Args) * 3 + 1> braces{}; constexpr const char c[4] = "{} "; for (auto i{0u}; i != braces.size() - 1; ++i) { braces[i] = c[i % 3]; } braces.back() = '\0'; raw_write_to_log(std::string_view{braces.data()}, std::make_format_args(args...)); } int main() { log("Number", "of", "arguments", "is", "arbitrary."); log("Any type that meets the `BasicFormatter` requirements", "can be printed."); log("For example:", 1, 2.0, '3', "*42*"); raw_write_to_log("{:02} │ {} │ {} │ {}", std::make_format_args(1, 2.0, '3', "4")); }
Output:
0000 : Number of arguments is arbitrary. 0001 : Any type that meets the `BasicFormatter` requirements can be printed. 0002 : For example: 1 2.0 3 *42* 0003 : 01 │ 2.0 │ 3 │ 4
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
P2418R2 | C++20 | objects that are neither const-usable nor copyable (such as generator-like objects) are not formattable |
allow formatting these objects |
LWG 3631 | C++20 | cv-qualified arguments were incorrectly handled after P2418R2 | handling corrected |
See also
(C++20)(C++20)(C++20) |
class that provides access to all formatting arguments (class template) |
(C++20) |
non-template variant of std::format using type-erased argument representation (function) |
(C++20) |
non-template variant of std::format_to using type-erased argument representation (function template) |