Skip to content

Instantly share code, notes, and snippets.

@dirocco
Created June 1, 2019 18:54
Show Gist options
  • Save dirocco/5f5a9ff35a765fe25850c2289964edfd to your computer and use it in GitHub Desktop.
Save dirocco/5f5a9ff35a765fe25850c2289964edfd to your computer and use it in GitHub Desktop.
#pragma once
/* Let's you map a non-contiguous enum class to a contiguously packed array for better performance
ie:
enum class ABC { A = 'A', B = 'B', C = 'C', D = 'D' };
typedef PackedEnum<ABC::B, ABC::A, ABC::C> PackedABC;
At compile time:
PackedABC::list wil be { ABC::B, ABC::A, ABC::C }
PackedABC::constIndexOf<ABC::A>() returns 1
PackedABC::constEnumOf(2) returns ABC::C
At run time:
PackedABC::indexOf(ABC::A) returns 1
PackedABC::enumOf(2) returns ABC::C
*/
template<auto firstval, auto... vallist>
struct PackedEnum {
typedef decltype(firstval) type;
constexpr static type list[] = { firstval, vallist... };
constexpr static uint_fast8_t length = sizeof(list) / sizeof(type);
template<type t>
constexpr static uint_fast8_t constIndexOfImpl()
{
uint_fast8_t i = 0;
while(i < length)
{
if(list[i] == t) return i;
++i;
};
return 0xff;
};
template<type t>
constexpr static bool containsVal() { return constIndexOfImpl<t>() != 0xff; }
template<type t>
constexpr static uint_fast8_t constIndexOf()
{
static_assert(containsVal<t>(), "constIndexOf called on unlisted value");
return constIndexOfImpl<t>();
}
static uint_fast8_t indexOf(type t)
{
uint_fast8_t i = 0;
while(i < length)
{
if(list[i] == t) return i;
++i;
};
return 0xff;
}
constexpr static type constEnumOf(uint_fast8_t i)
{
return (type)list[i];
}
static type enumOf(uint_fast8_t i)
{
return (type)list[i];
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment