// Online C++ compiler to run C++ program online
/******************************************************************************
Welcome to GDB Online.
GDB online is an online compiler and debugger tool for C, C++, Python, PHP, Ruby,
C#, OCaml, VB, Perl, Swift, Prolog, Javascript, Pascal, HTML, CSS, JS
Code, Compile, Run and Debug online from anywhere in world.
*******************************************************************************/
#include <iostream>
#include <typeinfo>
//#include <cxxabi.h>
#include <string.h>
#include <memory>
#include <array>
using u32 = uint32_t;
using s32 = int;
// The enum_name class provides a name function for a given enum type and value.
template<typename enum_type, enum_type enum_value>
class enum_name final {
// Helper function that directly takes an enum_type value template parameter to get the name of the classes template enum type value as a string.
template <enum_type value>
static const char* helper_name() {
// Clang compiler format: __PRETTY_FUNCTION__ = static const char *u_enum_name<ENUM_TYPE_NAME, ENUM_TYPE_NAME::ENUM_VALUE_NAME>::helper_value() [enum_type = ENUM_TYPE_NAME, enum_value = ENUM_TYPE_NAME::ENUM_VALUE_NAME, value = ENUM_TYPE_NAME::ENUM_VALUE_NAME]
// MSVC compiler format: __FUNCSIG__ = const char *__cdecl u_enum_name<enum ENUM_TYPE_NAME,ENUM_VALUE>::helper_value<ENUM_TYPE_NAME::ENUM_VALUE_NAME>(void)
static const unsigned long long function_name_length = sizeof(__PRETTY_FUNCTION__);
static const std::string function_name(__PRETTY_FUNCTION__);
static const unsigned long long type_name_start = function_name.rfind('=') + 2;
static const unsigned long long type_name_end = function_name_length - 2;
static const unsigned long long type_name_length = type_name_end - type_name_start;
static const std::string type_name_string = function_name.substr((size_t)type_name_start, (size_t)type_name_length);
return type_name_string.c_str();
}
public:
static const char* name() { return helper_name<enum_value>(); } // Get the name of the classes template enum type and value as a string.
};
struct token {
const char * name;
s32 id;
};
template<typename enum_type, enum_type begin, enum_type end>
struct token_holder {
constexpr static inline int count_values(enum_type type) {
return (type != end)
? count_values((enum_type)(s32(type)+1))
: (s32(type)+1);
}
static constexpr u32 N = count_values(begin);
using tokens = std::array<token, N+1>; // because have {0, 0} in last element
template<typename e_enum_type, e_enum_type enum_value>
constexpr token make_name() {
return { enum_name<e_enum_type, enum_value>().name(), enum_value };
}
template<typename e_enum_type, u32... Indices>
constexpr tokens make_tokens_helper(std::integer_sequence<u32, Indices...>) {
tokens ts = { make_name<e_enum_type, (e_enum_type)Indices>()... };
ts[N] = {0, 0};
return ts;
}
template<typename e_enum_type>
constexpr tokens make_tokens() {
return make_tokens_helper<e_enum_type>( std::make_integer_sequence<u32, N>{});
}
operator const token *() const { return values.unsafe_ptr(); }
const token *data() const { return values.unsafe_ptr(); }
constexpr token_holder() : values{make_tokens<enum_type>()} {}
tokens values;
};
enum test_enum { te_first, te_second, te_third, te_count };
int main() {
const token_holder<test_enum, te_first, te_count> test_tokens;
for (auto &s: test_tokens.values)
std::cout << "{" << (s.name ? s.name : "null") << ", " << s.id << " }" << std::endl;
return 0;
}