Skip to content

Instantly share code, notes, and snippets.

@lightdiscord
Last active October 6, 2021 23:17
Show Gist options
  • Save lightdiscord/8d6c135abc7245aa5bf12a95fcc1bf2d to your computer and use it in GitHub Desktop.
Save lightdiscord/8d6c135abc7245aa5bf12a95fcc1bf2d to your computer and use it in GitHub Desktop.
Solution to the enum and union without union because of destructors problem (sad c++98 noises), solution using templates.
#include <iostream>
#include <stdexcept>
#include <vector>
#include <string>
template <class T> struct size_of {
static const int size = sizeof(T);
};
template <> struct size_of<void> {
static const int size = 0;
};
#define _SIZE(a) (size_of<a>::size)
#define _MAX(a, b) ((a) > _SIZE(b) ? (a) : _SIZE(b))
template <class A = void, class B = void, class C = void, class D = void, class E = void> struct union_size {
static const int size = _MAX(_MAX(_MAX(_MAX(_MAX(0, A), B), C), D), E);
};
#undef _MAX
#undef _SIZE
template <class E, class T> struct variant_mapper {
};
class Enum {
public:
enum Type {
Int,
String
};
private:
Type _type;
char _data[union_size<int, std::string>::size];
Enum(void);
template <class T>
Enum(const T &value) {
_type = variant_mapper<Enum, T>::type;
new(_data) T(value);
}
template <class T>
void _destroy(T &value) {
value.~T();
}
public:
~Enum(void) {
switch (_type) {
case String:
_destroy(as<std::string>());
break;
case Int:
break;
}
}
template <class T>
bool is(void) const {
return _type == variant_mapper<Enum, T>::type;
}
template <class T>
T& as(void) {
if (_type != variant_mapper<Enum, T>::type) {
throw std::logic_error("Wrong type");
}
return reinterpret_cast<T&>(_data);
}
static Enum from_string(const std::string &value) {
return Enum(value);
}
static Enum from_int(const int &value) {
return Enum(value);
}
};
template <> struct variant_mapper<Enum, int> {
static const Enum::Type type = Enum::Int;
};
template <> struct variant_mapper<Enum, std::string> {
static const Enum::Type type = Enum::String;
};
int main(void) {
{
Enum value = Enum::from_string("Hello, world");
std::cout << value.is<std::string>() << std::endl;
std::cout << value.is<int>() << std::endl;
std::string &string = value.as<std::string>();
std::cout << string << std::endl;
}
{
Enum value = Enum::from_int(42);
std::cout << value.is<std::string>() << std::endl;
std::cout << value.is<int>() << std::endl;
int &number = value.as<int>();
std::cout << number << std::endl;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment