Какова каноническая реализация std::format для пользовательских типов?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Какова каноническая реализация std::format для пользовательских типов?

Сообщение Anonymous »

Я хочу написать код для пользовательского типа, чтобы он работал с std::format.

Код: Выделить всё

struct MyType {};

const auto my_type{MyType()};
const auto formatted{std::format("{}", my_type)};
Я обнаружил, что по этой теме существует множество разных источников, каждый из которых представляет несколько иное решение. Я подозреваю, что некоторые авторы (включая меня) нашли решение, которое компилируется и работает, но не обязательно является самым правильным решением.
Иногда код можно писать несколькими разными способами. Каждый вариант может означать что-то немного отличающееся. Следовательно, рабочих решений может быть несколько, но наиболее точной и правильной реализацией может быть только одно.
Вот одно из таких решений. (Ссылка)

Код: Выделить всё

struct MyType {
int a;
};

template 
struct std::formatter {
constexpr auto parse(std::format_parse_context& context) {
return context.begin();
}

auto format(const MyType& my_type, std::format_context& context) const {
return std::format_to(context.out(), "{}", my_type.a);
}
};
Возможно, это наиболее технически правильная и точная реализация.
Один аспект этой реализации, который не так привлекателен, заключается в том, что она включает определение автоматического анализа constexpr(std::format_parse_context& context), которое по сути ничего не делает. (Это просто шаблон, который тривиально возвращает context.begin().) Существуют и другие решения, которые этого не требуют. Но какой путь правильный?
Это второе решение не включает синтаксический анализ.

Код: Выделить всё

enum class CommandType {
QUIT
};

constexpr std::string_view to_string(const CommandType command_type) noexcept {
if (command_type == CommandType::QUIT) {
return "QUIT";
}
return "(UNKNOWN)";
}

template
struct std::formatter : std::formatter {

auto format(const CommandType command_type, std::format_context& context) const {
return std::formatter::format(to_string(command_type), context);
}
};
На самом деле это один из моих. Я взломал его с небольшой помощью LLM.
Что мне в нем нравится, так это то, что класс enum имеет дополнительный метод to_string, который преобразует значение перечисления в std::string_view. Мне не нравится тот факт, что он вызывается to_string, но возвращает std::string_view вместо std::string. При этом to_string — это ожидаемое имя, было бы странно называть его to_string_view.
Стоит отметить, что реализация std::formatter специфична для того факта, что форматируемый тип может быть представлен с использованием статического const char* . Он не содержит определения синтаксического анализа. Это унаследовано от std::formatter.
Преимущество этого в том, что нам не нужно писать синтаксический анализ. Но это будет работать только для типов, которые являются аналогами статических типов char*. (

Код: Выделить всё

struct MyType { int a; }
здесь не сработает.) Недостаток этого кода в том, что он вводит в заблуждение, поскольку предполагает, что CommandType является std::string_view.
Вот последний пример.

Код: Выделить всё

struct Position {
std::size_t x;
std::size_t y;
};

template
struct std::formatter : std::formatter {
auto format(const Position& position, auto& context) {
return std::format_to(
context.out(),
"({}, {})",
position.x,
position.y
);
}
};
Проблемы аналогичны предыдущему примеру. Position не является std::string, однако std::formatter наследуется от std::formatter.
Подобно перегрузке операторов, может показаться, что конкретные детали того, что форматируется, имеют значение. Если да, то это будет означать, что канонической реализации нет, но может существовать несколько наборов типов, каждый из которых имеет свою собственную каноническую реализацию. (

Код: Выделить всё

string_view
типа строки типа pod и т. д.)
Каковы правила реализации std::formatter для использования с std::format?

Подробнее здесь: https://stackoverflow.com/questions/798 ... stom-types
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»