std::make_format_args, std::make_wformat_args
Определено в заголовочном файле <format> | ||
|---|---|---|
template< class Context = std::format_context, class... Args >
/*format-arg-store*/<Context, Args...>
make_format_args( Args&... args );
| (1) | (начиная с C++20) |
template< class... Args >
/*format-arg-store*/<std::wformat_context, Args...>
make_wformat_args( Args&... args );
| (2) | (начиная с C++20) |
Возвращает объект, который хранит массив аргументов форматирования и может быть неявно преобразован в std::basic_format_args<Context>.
Поведение не определено, если typename Context::template formatter_type<std::remove_const_t<Ti>> не удовлетворяет требованиям BasicFormatter для любого Ti в Args.
Программа некорректна, если для любого типа Ti в Args, Ti не удовлетворяет требованиям __formattable_with<Context>.
return std::make_format_args<std::wformat_context>(args...);.Параметры
| args... | - | значения, используемые в качестве аргументов форматирования |
Возвращаемое значение
Объект, содержащий аргументы форматирования.
Для каждого аргумента t типа T пусть TD будет std::remove_const_t<std::remove_reference_t<T>>. Соответствующий std::basic_format_arg в результате определяется следующим образом:
- если
TDявляется bool илиContext::char_type,std::basic_format_argхранитt; - иначе, если
TDявляется char, аContext::char_type— wchar_t,std::basic_format_argхранитstatic_cast<wchar_t>(static_cast<unsigned char>(t)); - иначе, если
TDявляется знаковым целочисленным типом, размер которого не превышает размер int,std::basic_format_argхранитstatic_cast<int>(t); - иначе, если
TDявляется беззнаковым целочисленным типом, размер которого не превышает размер unsignedint,std::basic_format_argхранитstatic_cast<unsigned int>(t); - иначе, если
TDявляется знаковым целочисленным типом, размер которого не превышает размер longlong,std::basic_format_argхранитstatic_cast<long long>(t); - иначе, если
TDявляется беззнаковым целочисленным типом, размер которого не превышает размер unsignedlonglong,std::basic_format_argхранитstatic_cast<unsigned long long>(t); - иначе, если
TDявляется float, double или longdouble,std::basic_format_argхранитt; - иначе, если
TDявляется специализациейstd::basic_string_viewилиstd::basic_stringиTD::char_typeявляетсяContext::char_type,std::basic_format_argхранитstd::basic_string_view<Context::char_type>(t.data(), t.size()); - иначе, если
std::decay_t<TD>являетсяContext::char_type*илиconst Context::char_type*,std::basic_format_argхранитstatic_cast<const Context::char_type*>(t); - иначе, если
std::is_void_v<std::remove_pointer_t<TD>>являетсяtrueилиstd::is_null_pointer_v<TD>являетсяtrue,std::basic_format_argхранитstatic_cast<const void*>(t); - иначе
std::basic_format_argхранитstd::basic_format_arg<Context>::handleдляtвместе с дополнительными данными, необходимыми дляhandle::format().
Примечания
Для типов, определённых пользователем, аргумент форматирования имеет семантику ссылки и не продлевает время жизни args. Программист должен обеспечить, чтобы args существовали дольше возвращаемого значения. Обычно результат используется только в качестве аргумента функции форматирования.
| Макрос проверки поддержки функциональности | Значение | Стандарт | Функциональность |
|---|---|---|---|
__cpp_lib_format_uchar | 202311L |
(C++20) (отчёт об ошибке) | Форматирование кодовых единиц как беззнаковых целых чисел |
Пример
#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{0uz}; 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...));
}
template<typename T>
const T& unmove(T&& x)
{
return x;
}
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(unmove(1), unmove(2.0), unmove('3'), "4"));
}
Вывод:
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
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были ретроактивно применены к ранее опубликованным стандартам C++.
| Отчёт об ошибке | Применяется к | Опубликованное поведение | Корректное поведение |
|---|---|---|---|
| P2418R2 | C++20 | объекты, которые нельзя ни использовать как константные, ни копировать (например, объекты, похожие на генераторы), не являются форматируемыми | разрешено форматирование таких объектов |
| P2905R2 | C++20 |
make_format_args принимала аргументы-правые значения посредством forwarding references | принимает только ссылки на lvalue |
| P2909R4 | C++20 |
char или wchar_t могли форматироваться как беззнаковые целые значения вне допустимого диапазона | перед таким форматированием кодовые единицы преобразуются в соответствующий беззнаковый тип |
| LWG 3631 | C++20 | аргументы с квалификаторами cv некорректно обрабатывались после P2418R2 | обработка исправлена |
См. также
|
(C++20)(C++20)(C++20) | класс, предоставляющий доступ ко всем аргументам форматирования (шаблон класса) |
|
(C++20) | нетемплейтный вариант std::format с использованием представления аргументов с устранением типов (функция) |
|
(C++20) | нетемплейтный вариант std::format_to с использованием представления аргументов с устранением типов (шаблон функции) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/utility/format/make_format_args