Skip to content

Instantly share code, notes, and snippets.

@Hasenpfote
Last active August 9, 2019 01:30
Show Gist options
  • Save Hasenpfote/de66ea851d607adf6500fbc2493786bc to your computer and use it in GitHub Desktop.
Save Hasenpfote/de66ea851d607adf6500fbc2493786bc to your computer and use it in GitHub Desktop.
debugging enums in c++17
#include <iostream>
#include "util.h"
struct Foo
{
enum class Color
{
Red = 2, Green = 5, Blue = 10,
};
};
template<typename T>
constexpr auto underlying_cast(T x)
{
static_assert(std::is_enum_v<T>, "x is not an enum type.");
return static_cast<std::underlying_type_t<T>>(x);
}
template<typename T, T v>
constexpr auto enum_as_string()
{
using namespace util;
#if defined(_MSC_VER)
auto src = std::string_view(__FUNCSIG__);
// auto __cdecl extract_enum_from_sig<enum main::Color,main::Color::Green>(void)
auto leftover = src.substr(src.find(__FUNCTION__));
// extract_enum_from_sig<enum main::Color,main::Color::Green>(void)
leftover = extract_between(leftover, '<', '>');
// enum main::Color,main::Color::Green
return split_last(leftover, ':').second;
#elif defined(__clang__)
auto leftover = std::string_view(__PRETTY_FUNCTION__);
// auto extract_enum_from_sig() [T = Color, v = main()::Color::Green]
leftover = extract_between(leftover, '[', ']');
// T = Color, v = main()::Color::Green
return split_last(leftover, ':').second;
#elif defined(__GNUC__)
auto leftover = std::string_view(__PRETTY_FUNCTION__);
// constexpr auto extract_enum_from_sig() [with T = main()::Color; T v = main::Color::Green]
leftover = extract_between(leftover, '[', ']');
// with T = main()::Color; T v = main::Color::Green
return split_last(leftover, ':').second;
#else
#error "No implementation available!"
#endif
}
int main()
{
{
constexpr auto color = Foo::Color::Green;
constexpr auto s = enum_as_string<Foo::Color, color>();
constexpr auto id = underlying_cast(color);
std::cout << "color: " << s << "(" << id << ")" << std::endl;
}
{
constexpr auto color = static_cast<Foo::Color>(10);
constexpr auto s = enum_as_string<Foo::Color, color>();
constexpr auto id = underlying_cast(color);
std::cout << "color: " << s << "(" << id << ")" << std::endl;
}
{
constexpr auto color = static_cast<Foo::Color>(100);
constexpr auto s = enum_as_string<Foo::Color, color>();
constexpr auto id = underlying_cast(color);
std::cout << "color: " << s << "(" << id << ")" << std::endl;
}
return 0;
}
#pragma once
#include <cstddef>
#include <string_view>
#include <array>
#include <utility>
#include <algorithm>
namespace util
{
inline constexpr std::string_view
ltrim(std::string_view s)
{
auto pos = s.find_first_not_of(' ');
auto n = (pos == std::string_view::npos) ? s.size() : pos;
s.remove_prefix(n);
return s;
}
inline constexpr std::string_view
rtrim(std::string_view s)
{
auto pos = s.find_last_not_of(' ');
auto n = (pos == std::string_view::npos) ? s.size() : s.size() - pos - static_cast<decltype(pos)>(1);
s.remove_suffix(n);
return s;
}
inline constexpr std::string_view
trim(std::string_view s)
{
return rtrim(ltrim(s));
}
inline constexpr std::string_view
extract_between(std::string_view s, std::string_view::value_type sep1, std::string_view::value_type sep2)
{
auto s_pos = s.find_first_of(sep1);
auto e_pos = s.find_last_of(sep2);
if(s_pos == std::string_view::npos || e_pos == std::string_view::npos)
return std::string_view();
s_pos += static_cast<decltype(s_pos)>(1);
return s.substr(s_pos, e_pos - s_pos);
}
inline constexpr std::pair<std::string_view, std::string_view>
split_first(std::string_view s, std::string_view::value_type delimiter)
{
auto pos = s.find_first_of(delimiter);
if(pos == std::string_view::npos)
return std::make_pair(trim(s), std::string_view());
else if(pos == 0)
return std::make_pair(std::string_view(), trim(s.substr(1)));
else if(pos == (s.size() - static_cast<std::string_view::size_type>(1)))
return std::make_pair(trim(s.substr(0, pos)), std::string_view());
else
return std::make_pair(trim(s.substr(0, pos)), trim(s.substr(pos + static_cast<decltype(pos)>(1))));
}
inline constexpr std::pair<std::string_view, std::string_view>
split_last(std::string_view s, std::string_view::value_type delimiter)
{
auto pos = s.find_last_of(delimiter);
if(pos == std::string_view::npos)
return std::make_pair(std::string_view(), trim(s));
else if(pos == 0)
return std::make_pair(std::string_view(), trim(s.substr(1)));
else if(pos == (s.size() - static_cast<std::string_view::size_type>(1)))
return std::make_pair(trim(s.substr(0, pos)), std::string_view());
else
return std::make_pair(trim(s.substr(0, pos)), trim(s.substr(pos + static_cast<decltype(pos)>(1))));
}
} // namespace util
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment