Reflexión en tiempo de compilación de C ++ 1: obtenga el nombre del tipo de enumeración

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

  1. El código de clang will arriba se __PRETTY_FUNCTION__reemplazaauto enum_info::details::enum_type_name() [Enum_type = B]
  2. gcc codificará arriba es __PRETTY_FUNCTION__reemplazadoconstexpr auto enum_info::details::enum_type_name() [with Enum_type = B]
  3. 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.

Supongo que te gusta

Origin blog.csdn.net/m0_47534090/article/details/108571404
Recomendado
Clasificación