Last active
October 6, 2021 23:17
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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