Как печатать значения enum в C++23 #
Допустим, у нас есть enum или enum class. Как обеспечить печать его значений в целях диагностики и отладки?
Задача #
Допустим, в заголовочном файле объявлен enum class ast::BinaryOperation с такими значениями:
#pragma once
namespace ast
{
enum class BinaryOperation
{
Add,
Subtract,
Multiply,
Divide,
};
} // namespace ast
Нужно уметь выводить человеко-читаемое значение BinaryOperation в std::ostream, с помощью std::format и просто конкатенировать с какими-либо строками.
Предупреждение #
Возможно, в вашем проекте уже есть универсальный способ печати значений enum или сопоставления enum со значением:
- такое решение сложно написать с нуля;
- но если оно уже есть — используйте.
Решение #
Перепишем заголовочный файл, добавив следующее:
- заголовочные файлы
- функцию
binaryOperationName - оператор вывода в
std::ostream - специализацию шаблона
std::formatter
Новая версия:
#pragma once
#include <format>
#include <iosfwd>
#include <string_view>
namespace ast
{
enum class BinaryOperation
{
Add,
Subtract,
Multiply,
Divide,
};
std::string_view binaryOperationName(BinaryOperation operation);
// Поддержка вывода в std::ostream.
std::ostream& operator<<(std::ostream& os, BinaryOperation operation);
} // namespace ast
// Поддержка std::format(...).
template<>
struct std::formatter<ast::BinaryOperation> : std::formatter<string_view>
{
auto format(const ast::BinaryOperation& value, std::format_context& ctx) const
{
std::string_view name = ast::binaryOperationName(value);
return std::formatter<std::string_view>::format(name, ctx);
}
};Затем добавим файл BinaryOperation.cpp:
#include "BinaryOperation.h"
namespace ast
{
std::string_view binaryOperationName(BinaryOperation operation)
{
switch (operation)
{
case BinaryOperation::Add:
return "Add";
case BinaryOperation::Subtract:
return "Subtract";
case BinaryOperation::Multiply:
return "Multiply";
case BinaryOperation::Divide:
return "Divide";
default:
return "!!Unknown!!";
}
}
std::ostream& operator<<(std::ostream& os, BinaryOperation type)
{
os << binaryOperationName(type);
return os;
}
}Особенности #
- Функция
binaryOperationNameпозволяет поддержать сценарии, которые вы не могли предусмотреть при написанииBinaryOperation - При неожиданном значении выводится
"!!Unknown!!"вместо выброса исключения - Можно сделать всё header-only, но я лично не сторонник такого подхода