C++枚举类型转字符串
1. 参考
【鲜为人知的C++黑科技【PRETTY_FUNCTION】非侵入式的编译期反射-哔哩哔哩】
2. 源码
enum_enhanced.hpp
/**
* @file enum_enhanced.hpp
* @author chenpi001 (cp12138@duck.com)
* @brief convertion between enum and std::string, need c++11 or above
* @version 0.1
* @date 2022-08-03
*
* @copyright Copyright (c) 2022
*
*/
#pragma once
#include <string>
#include <type_traits>
namespace enum_enhanced
{
namespace enum_enhanced_impl
{
template <class T, T N>
char const *pretty_string()
{
#ifdef _MSC_VER
return __FUNCSIG__;
#else
return __PRETTY_FUNCTION__;
#endif
}
template <class T>
struct PrettyStringCaller
{
public:
int n;
std::string &s;
public:
template <int I>
void Call() const
{
if (n == I)
s = pretty_string<T, static_cast<T>(I)>();
}
};
template <int Start, int End, class F>
typename std::enable_if<Start == End>::type static_for(F const &caller) {}
template <int Start, int End, class F>
typename std::enable_if<Start != End>::type static_for(F const &caller)
{
caller.template Call<Start>();
static_for<Start + 1, End>(caller);
}
} // namespace enum_enhanced_imple
template <class T, int Start = 0, int End = 64>
std::string enum_to_string(T n)
{
static_assert(Start < End);
using namespace enum_enhanced_impl;
std::string string;
static_for<Start, End>(PrettyStringCaller<T>{.n = static_cast<int>(n), .s = string});
#ifdef _MSC_VER
size_t end = string.find_last_of('>');
size_t start = string.find_last_of(',', end) + 1;
#else
size_t start = string.find("N = ") + 4;
size_t end = string.find(']', start);
#endif
string = string.substr(start, end - start);
if ((start = string.find_last_of(":")) != string.npos)
{
string = string.substr(start + 1, string.size() - start);
}
return string;
}
template <class T, int Start = 0, int End = 64>
T enum_from_string(std::string const &str)
{
static_assert(Start < End);
using namespace enum_enhanced_impl;
for (int i = Start; i < End; i++)
{
if (!str.compare(enum_to_string<T, Start, End>(static_cast<T>(i))))
{
return static_cast<T>(i);
}
}
throw;
}
} // namespace enum_enhanced
main.cpp
#include <iostream>
#include "enum_enhanced.hpp"
enum Student
{
Bob,
Lisa = 10,
Ada
};
int main(int argc, char **argv)
{
Student a = Student::Bob;
std::cout << enum_enhanced::enum_to_string(a) << std::endl;
std::cout << enum_enhanced::enum_to_string(Student::Ada) << std::endl;
return 0;
}
输出
Bob
Ada
3. 注意
- 强烈推荐参考讲解自己实现,加强对元编程的理解
- 需要C++标准为C++11或以上,参考的原作者提供了C++98的实现方法
- 默认枚举类型的范围为[0,64],如果超过范围可主动设置模板中的Start和End值
- 会导致编译时间增加
- 只在gcc下使用过,理论上适配了msvc
本文介绍了如何在C++中实现枚举类型转字符串的功能,采用非侵入式静态反射的方法,适用于C++11及以上标准。详细讲述了参考资源、源码实现以及需要注意的事项,特别指出该方法在GCC下测试通过,理论上也兼容MSVC,但可能会增加编译时间。
134

被折叠的 条评论
为什么被折叠?



