#include<type_traits>
#include<cstdint>
struct Not_base {
constexpr Not_base() {}
template<typename T>
constexpr Not_base(T&& a) {} //just a place holder
};
template<typename T, typename Base= Not_base>
//Base must be another wrapper object
struct Enum_wrapper: Base {
using Enum_t=T;
Enum_t enumerator;
bool is_initialized;
using Base_t= Base;
constexpr Enum_wrapper() {}
constexpr Enum_wrapper(Enum_t a):
enumerator{a}, is_initialized{true} {}
template<typename Other_Enum_t>
requires(std::is_scoped_enum_v<Other_Enum_t>)
constexpr Enum_wrapper(Other_Enum_t a): Base{a}, enumerator{}, is_initialized{false} {}
//One could optionally (to make it even better) append/add:
/*
using enum Enum_t;
using Base;
Or Anything equavulent to the two lines above
*/
};
template <typename Enum_wrapper, Enum_wrapper obj,template<typename T, T obj_nested> typename correct_enum>
consteval auto potential_base() {
using potential_base= typename Enum_wrapper::Base_t;
if constexpr (!obj.is_initialized) {
if constexpr (std::is_same_v<potential_base,Not_base>) {
static_assert(true, "not found");
return;
}
else {
return correct_enum<potential_base, potential_base{obj}> {};
}
}
else {
static_assert(true, "not found");
return;
}
}
template<typename Enum_wrapper, Enum_wrapper obj>
struct correct_enum {
using potential_base_t=
decltype(
potential_base<Enum_wrapper, obj, correct_enum>()
);
using enum_t=
std::conditional_t<
obj.is_initialized,
typename Enum_wrapper::Enum_t,
typename potential_base_t::enum_t
>;
static constexpr enum_t enum_v = obj.is_initialized ? obj.enumerator : potential_base_t::enum_v;
};
template<template<std::uintmax_t N_> class bc, std::uintmax_t N>
struct exist {
//million credits to
//https://www.lukas-barth.net/blog/checking-if-specialized/
//for saving me here:
template<typename exist_if_exist= decltype(std::declval<bc<c...>>().~bc<c...>())>
bool static does() {
return true;
}
bool static does() {
return false;
}
};
namespace {
template<std::uintmax_t N=0>
struct sequential_count {
consteval static std::uintmax_t get_num() {
if(exist<sequential_count, N+1>::does()) {
return sequential_count<N+2>::get_num()
}
else {
sequential_count<N+1> dummy{};
return N+1;
}
}
};
}
template<typename intermediate_enum_wrapper, std::uintmax_t N= sequential_count::get_num()>
struct Enum_wrapper_complete {
template<template<typename T, std::uintmax_t N>
struct object_list {
//million credits to
//https://www.lukas-barth.net/blog/checking-if-specialized/
//for saving me here:
template<typename exist_if_exist= decltype(std::declval<bc<c...>>().~bc<c...>())>
consteval static bool does_exist() {
return true;
}
consteval static bool does_exist() {
return false;
}
static constexpr T obj;
};
template<template<typename T_, std::uintmax_t N_> class bc, typename T, signed minus= 0, std::uintmax_t N=0>
struct sequential_enum_count {
consteval static std::uintmax_t get_num(signed minus) {
if(object_list<sequential_count, N+1>::does_exist()) {
return sequential_enum_count<N+2>::get_num();
}
else {
sequential_enum_count<N+1-minus> dummy{};
return N+1-minus;
}
}
};
constexpr Enum_wrapper_complete(intermediate_enum_wrapper a) {
object_list<intermediate_enum_wrapper, sequential_enum_count<intermediate_enum_wrapper>>::obj = a;
}
consteval operator typename correct_enum<intermediate_enum_wrapper,
object_list<intermediate_enum_wrapper, sequential_enum_count<intermediate_enum_wrapper, 1>>::obj
>::enum_t()
{
return correct_enum<
intermediate_enum_wrapper,
object_list<intermediate_enum_wrapper, sequential_enum_count<intermediate_enum_wrapper, 1>>::obj;
}
};
int main()
{
enum class A { voilet, blue, roses, red};
constexpr A enum_obj= A::blue;
Enum_wrapper B{enum_obj};
Enum_wrapper_complete wrap{B};
return 0;
}