C++ compile-time reflection 1-get the enumeration type name

C++ compile-time reflection 1-get the enumeration type name

Note: I am original, if you find similarities, you will be responsible for the consequences

Sometimes we need to get type information. Type name, enumeration value name, etc. C++ does not support compile-time reflection for the time being (C++ 23/26 will support), but we can implement it ourselves, the disadvantage is that it will delay compilation speed.

Development environment:

Support msvc , clang and g++ , C++17 or above is required

achieve:

// 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

principle:

When the template is instantiated, the compiler will replace __FUNCSIG__or replace __PRETTY_FUNCTION__the function information including the template parameter information

  1. clang will code above is __PRETTY_FUNCTION__replacedauto enum_info::details::enum_type_name() [Enum_type = B]
  2. gcc will code above is __PRETTY_FUNCTION__replacedconstexpr auto enum_info::details::enum_type_name() [with Enum_type = B]
  3. msvc will code above is __FUNCSIG__replacedauto __cdecl enum_info::details::enum_type_name<enum main::B>(void)

Only the offset is needed later to get the name of the enumeration type

use:

// 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;
}

In the next issue, we will get the name of the enumeration value.

Guess you like

Origin blog.csdn.net/m0_47534090/article/details/108571404