Daily bit(e) C++. std::type_index, boost::type_index

Добавлено 29 июля 2023 в 17:40

Daily bit(e) C++ #201. Преобразование std::type_info в читабельные имена типов с помощью C++11 std::type_index и boost::type_index.

Daily bit(e) C++ #201. std::type_index, boost::type_index

Объект std::type_info, возвращаемый оператором typeid, не обеспечивает удобного для чтения человеком имени типа.

Мы можем смягчить эту проблему вручную, полагаясь на C++11 std::type_index и вручную отслеживая преобразование между std::type_info и любой необходимой информацией.

#include <unordered_map>
#include <string>
#include <typeindex>
#include <iostream>

struct A { virtual void fun() {} };
struct B : A {};

std::unordered_map<std::type_index, std::string> names;

void inspector(A& a) {
    std::cout << names[typeid(a)] << "\n";
}


// Заполняем наш пользовательский словарь
names[typeid(A)] = "Base";
names[typeid(B)] = "Derived";
names[typeid(int)] = "int";
names[typeid(double)] = "double";

int x = 20;
double y = 2.4;
std::cout << names[typeid(x)] << "\n";
// напечатает: "int"
std::cout << names[typeid(y)] << "\n";
// напечатает: "double"

A a;
B b;
inspector(a);
// напечатает: "Base"
inspector(b);
// напечатает: "Derived"

Открыть пример на Compiler Explorer.

В качестве альтернативы, можно использовать библиотеку boost::type_index, которая предоставляет дополнительные функции.

#include <boost/type_index.hpp>
#include <unordered_map>
#include <vector>
#include <string>
#include <iostream>

namespace bti = boost::typeindex;

struct A { virtual void fun() {} };
struct B : A {};

void inspector(A& a) {
    std::cout << bti::type_id_runtime(a).pretty_name() << "\n";
}


// Информация о типе времени компиляции:
int x = 20;
double y = 2.4;
std::cout << bti::type_id<decltype(x)>().pretty_name() << "\n";
// напечатает: "int"
std::cout << bti::type_id<decltype(y)>().pretty_name() << "\n";
// напечатает: "double"

// Информация о типе времени выполнения:
A a;
B b;
inspector(a);
// напечатает: "A"
inspector(b);
// напечатает: "B"

// Также поддерживает cv-квалификаторы (const и volatile) (typeid нет)
std::cout << bti::type_id_with_cvr<const int>().pretty_name() << "\n";
// напечатает: "int const"

// Также можно распутывать сложные вложенные типы
using nested = std::unordered_map<A,std::vector<std::string>>;
std::cout << bti::type_id<nested>().pretty_name();
// напечатает(GCC): "std::unordered_map<A, std::vector<
//                  std::__cxx11::basic_string<char...

Открыть пример на Compiler Explorer.

Теги

BoostC++ / CppC++11Daily bit(e) C++Программирование

На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.

В случае комментирования в качестве гостя (без регистрации на disqus.com) для публикации комментария требуется время на премодерацию.