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.
Поведение не определено, если typename Context::template formatter_type<std::remove_cvref_t<Ti>> не соответствует требованиям BasicFormatter для любого Ti в Args.
Программа некорректна, если для любого типа Ti в Args, std::remove_reference_t<Ti> не соответствует __formattable_with<Context>.
return std::make_format_args<std::wformat_context>(std::forward<Args>(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>(t); - иначе, если
TDявляется целочисленным типом со знаком, размер которого не превышаетint, то std::basic_format_arg хранитstatic_cast<int>(t); - иначе, если
TDпредставляет собой целочисленный тип без знака, размер которого не превышаетunsigned int, то std::basic_format_arg хранитstatic_cast<unsigned int>(t); - иначе, если
TDявляется целочисленным типом со знаком, размер которого не превышаетlong long, то std::basic_format_arg хранитstatic_cast<long long>(t); - иначе, если
TDпредставляет собой целочисленный тип без знака, размер которого не превышаетunsigned long long, то std::basic_format_arg хранитstatic_cast<unsigned long long>(t); - иначе, если
TDэтоfloat,doubleилиlong double, то 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 пережил возвращаемое значение. Обычно результат используется только как аргумент функции форматирования.
Пример
#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)
{
// Создаёт строку форматирования "{} "...
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...));
}
int main()
{
log("Количество", "аргументов", "произвольно.");
log("Любой тип, соответствующий требованиям BasicFormatter,", "можно распечатать.");
log("Например:", 1, 2.0, '3', "*42*");
raw_write_to_log("{:02} │ {} │ {} │ {}", std::make_format_args(1, 2.0, '3', "4"));
}
Вывод:
0000 : Количество аргументов произвольно.
0001 : Любой тип, соответствующий требованиям BasicFormatter, можно распечатать.
0002 : Например: 1 2.0 3 *42*
0003 : 01 │ 2.0 │ 3 │ 4
Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
| Номер | Применён | Поведение в стандарте | Корректное поведение |
|---|---|---|---|
| WG не указан | C++20 | объекты, которые не являются ни константными, ни копируемыми (например, объекты, подобные генераторам), не форматируются |
форматирование этих объектов разрешено |
| LWG 3631 | c++20 | cv-квалифицированные аргументы неправильно обрабатывались после P2418R2 |
обработка исправлена |
Смотрите также
(C++20)(C++20)(C++20) |
класс, который обеспечивает доступ ко всем аргументам форматирования (шаблон класса) |
(C++20) |
нешаблонный вариант std::format с использованием представления аргументов с удалением типа (функция) |
(C++20) |
нешаблонный вариант std::format_to с использованием представления аргументов с удалением типа (шаблон функции) |