Reflexión en tiempo de compilación de C ++ 1: obtenga el nombre del tipo de enumeración
Nota: soy original, si encuentras similitudes tu serás responsable de las consecuencias
A veces necesitamos obtener información del tipo. Nombre del tipo, nombre del valor de enumeración, etc. C ++ no admite la reflexión en tiempo de compilación por el momento (C ++ 23/26 lo admitirá), pero podemos implementarlo nosotros mismos, la desventaja es que retrasará la velocidad de compilación.
Entorno de desarrollo:
Se requiere soporte msvc , clang y g ++ , C ++ 17 o superior
lograr:
// enum_info.hpp
#ifndef ENUM_INFO_HPP
#define ENUM_INFO_HPP
#include <cstddef>
#include <string_view>
#include <type_traits>
namespace enum_info
{
using string_view = std::string_view;
namespace details
{
template <typename Enum_type>
constexpr auto enum_type_name() noexcept
{
// 静态断言, Enum_type 必须是枚举类型
static_assert(std::is_enum_v<Enum_type>, " requires Enum_type == enum");
#if defined(__clang__)
// __PRETTY_FUNCTION__:
// auto enum_info::details::enum_type_name() [Enum_type = B]
constexpr std::size_t prefix = sizeof("auto enum_info::details::enum_type_name() [Enum_type = ") - 1;
constexpr std::size_t suffix = sizeof("]") - 1;
constexpr string_view name{
__PRETTY_FUNCTION__ + prefix, sizeof(__PRETTY_FUNCTION__) - prefix - suffix - 1 };
#elif defined(__GNUC__)
// __PRETTY_FUNCTION__:
// constexpr auto enum_info::details::enum_type_name() [with Enum_type = B]
constexpr std::size_t prefix = sizeof("constexpr auto enum_info::details::enum_type_name() [with Enum_type = ") - 1;
constexpr std::size_t suffix = sizeof("]") - 1;
constexpr string_view name{
__PRETTY_FUNCTION__ + prefix, sizeof(__PRETTY_FUNCTION__) - prefix - suffix - 1 };
#elif defined(_MSC_VER)
// __FUNCSIG__:
// auto __cdecl enum_info::details::enum_type_name<enum main::B>(void) noexcept
constexpr std::size_t prefix = sizeof("auto __cdecl enum_info::details::enum_type_name<enum ") - 1;
constexpr std::size_t suffix = sizeof(">(void) noexcept") - 1;
constexpr string_view name{
__FUNCSIG__ + prefix, sizeof(__FUNCSIG__) - prefix - suffix - 1 };
#endif
return name;
}
} // details
template <typename Enum_type>
inline constexpr string_view enum_type_name_v = details::enum_type_name<Enum_type>();
} // enum_info
#endif // !ENUM_INFO_HPP
principio:
Cuando se crea una instancia de la plantilla, el compilador reemplazará __FUNCSIG__
o reemplazará __PRETTY_FUNCTION__
la información de la función, incluida la información de los parámetros de la plantilla
- El código de clang will arriba se
__PRETTY_FUNCTION__
reemplazaauto enum_info::details::enum_type_name() [Enum_type = B]
- gcc codificará arriba es
__PRETTY_FUNCTION__
reemplazadoconstexpr auto enum_info::details::enum_type_name() [with Enum_type = B]
- msvc se
__FUNCSIG__
reemplaza el código anteriorauto __cdecl enum_info::details::enum_type_name<enum main::B>(void)
Solo se necesita el desplazamiento más adelante para obtener el nombre del tipo de enumeración
utilizar:
// main.cpp
// clang编译器
#include <iostream>
#include "enum_info.hpp"
enum class my_enum
{
};
int main(void)
{
std::cout << enum_info::enum_type_name_v<my_enum> << std::endl;
(void)getchar();
return 0;
}
En el próximo número, obtendremos el nombre del valor de enumeración.