C++ 编译期反射1 - 获取枚举的类型名

C++ 编译期反射1 - 获取枚举的类型名

注意: 本人是原创, 如若发现雷同,后果自负

有时我们需要获取类型的信息. 类型名, 枚举值的名, 等等. C++ 暂时不支持编译期反射(C++ 23/26会支持), 但是我们可以自己实现, 缺点就是会拖延编译速度.

开发环境:

支持 msvc, clangg++, 需要C++17以上

实现:

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

原理:

在模板实例化的时候, 编译器将替换__FUNCSIG____PRETTY_FUNCTION__为函数的信息包括模板参数的信息

  1. clang 会把上面代码里的 __PRETTY_FUNCTION__ 替换成 auto enum_info::details::enum_type_name() [Enum_type = B]
  2. gcc 会把上面代码里的 __PRETTY_FUNCTION__ 替换成 constexpr auto enum_info::details::enum_type_name() [with Enum_type = B]
  3. msvc 会把上面代码里的 __FUNCSIG__ 替换成 auto __cdecl enum_info::details::enum_type_name<enum main::B>(void)

后面只需要偏移就可以获取枚举类型的名称

使用:

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

下期讲获取枚举值的名.

猜你喜欢

转载自blog.csdn.net/m0_47534090/article/details/108571404
今日推荐