Created
August 15, 2018 19:39
-
-
Save Rseding91/b63189f13f538e4a26ed627f48fd0a45 to your computer and use it in GitHub Desktop.
MacroVariant
This file contains 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 <MacroVariant.hpp> | |
bool MacroVariant::isCorrectDataTypeForAction(MacroVariantType action, const std::type_info& type) | |
{ | |
switch (action) | |
{ | |
#define ADD_CASE(ACTION, PREFIX, TYPE, VALUE) \ | |
case MacroVariantType::ACTION: return typeid(std::remove_cv<PREFIX TYPE>) == type; | |
CALL_ON_EVERY_TYPE_WITH_DATA(ADD_CASE) | |
#undef ADD_CASE | |
default: | |
return false; | |
} | |
} | |
MacroVariant::MacroVariant(MacroVariantType type) | |
: type(type) | |
{ | |
this->initValue(); | |
} | |
MacroVariant::MacroVariant(MacroVariant&& other) noexcept | |
{ | |
this->emplaceConstructFrom(std::move(other)); | |
} | |
MacroVariant::MacroVariant(const MacroVariant& other) | |
{ | |
this->emplaceConstructFrom(other); | |
} | |
MacroVariant::~MacroVariant() | |
{ | |
this->destroyValue(); | |
} | |
MacroVariant& MacroVariant::operator=(MacroVariant&& other) noexcept | |
{ | |
this->destroyValue(); | |
this->emplaceConstructFrom(std::move(other)); | |
return *this; | |
} | |
MacroVariant& MacroVariant::operator=(const MacroVariant& other) | |
{ | |
this->destroyValue(); | |
this->emplaceConstructFrom(other); | |
return *this; | |
} | |
void MacroVariant::emplaceConstructFrom(const MacroVariant& other) | |
{ | |
this->type = other.type; | |
switch (this->type) | |
{ | |
#define CALL_CONSTRUCT(ACTION, PREFIX, TYPE, VALUE) \ | |
case MacroVariantType::ACTION: new(&this->VALUE) PREFIX TYPE (other.VALUE); break; | |
CALL_ON_EVERY_TYPE_WITH_DATA(CALL_CONSTRUCT) | |
#undef CALL_CONSTRUCT | |
case MacroVariantType::Nothing: | |
break; | |
} | |
} | |
void MacroVariant::emplaceConstructFrom(MacroVariant&& other) noexcept | |
{ | |
this->type = other.type; | |
switch (this->type) | |
{ | |
#define CALL_CONSTRUCT(ACTION, PREFIX, TYPE, VALUE) \ | |
case MacroVariantType::ACTION: new(&this->VALUE) PREFIX TYPE (std::move(other.VALUE)); break; | |
CALL_ON_EVERY_TYPE_WITH_DATA(CALL_CONSTRUCT) | |
#undef CALL_CONSTRUCT | |
case MacroVariantType::Nothing: | |
break; | |
} | |
} | |
void MacroVariant::clear() | |
{ | |
this->destroyValue(); | |
this->type = MacroVariantType::Nothing; | |
} | |
namespace MacroVariantHelper | |
{ | |
template<class T> | |
void call_destructor(T& value) | |
{ | |
value.~T(); | |
} | |
} | |
void MacroVariant::destroyValue() | |
{ | |
switch (this->type) | |
{ | |
#define CALL_DESTRUCTOR(ACTION, PREFIX, TYPE, VALUE) \ | |
case MacroVariantType::ACTION: MacroVariantHelper::call_destructor(this->VALUE); break; | |
CALL_ON_EVERY_TYPE_WITH_DATA(CALL_DESTRUCTOR) | |
#undef CALL_DESTRUCTOR | |
case MacroVariantType::Nothing: | |
break; | |
} | |
} | |
void MacroVariant::initValue() | |
{ | |
switch (this->type) | |
{ | |
#define CALL_CONSTRUCTOR(ACTION, PREFIX, TYPE, VALUE) \ | |
case MacroVariantType::ACTION: new(&this->VALUE) PREFIX TYPE {}; break; | |
CALL_ON_EVERY_TYPE_WITH_DATA(CALL_CONSTRUCTOR) | |
#undef CALL_CONSTRUCTOR | |
case MacroVariantType::Nothing: | |
break; | |
} | |
} |
This file contains 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
#pragma once | |
#include <cassert> | |
#include <string> | |
#include <type_traits> | |
#define CALL_ON_EVERY_TYPE_WITH_NO_DATA(MACRO) \ | |
MACRO(Nothing) | |
#define CALL_ON_EVERY_TYPE_WITH_DATA(MACRO) \ | |
MACRO(Bool,, bool, boolValue) \ | |
MACRO(String, std::, string, stringValue) \ | |
MACRO(IntPointer, , int*, intPointer) | |
enum class MacroVariantType | |
{ | |
#define CREATE_TYPE(NAME) \ | |
NAME, | |
CALL_ON_EVERY_TYPE_WITH_NO_DATA(CREATE_TYPE) | |
#undef CREATE_TYPE | |
#define CREATE_TYPE(NAME, PREFIX, TYPE, VALUE) \ | |
NAME, | |
CALL_ON_EVERY_TYPE_WITH_DATA(CREATE_TYPE) | |
#undef CREATE_TYPE | |
}; | |
class MacroVariant | |
{ | |
public: | |
#define CALL_ON_EVERY_DATA_TYPE(MACRO) \ | |
MACRO(, bool,, boolValue) \ | |
MACRO(std::, string,, stringValue) \ | |
MACRO(, int, *, intPointer) | |
static bool isCorrectDataTypeForAction(MacroVariantType action, const std::type_info& type); | |
MacroVariant() : type(MacroVariantType::Nothing) {} | |
MacroVariant(MacroVariantType type); | |
MacroVariant(MacroVariant&& other) noexcept; | |
MacroVariant(const MacroVariant& other); | |
~MacroVariant(); | |
#define CREATE_CONSTRUCTOR(PREFIX, TYPE, POINTER, NAME) \ | |
MacroVariant(MacroVariantType type, PREFIX TYPE POINTER const& value) : type(type), NAME(value) \ | |
{ \ | |
assert(MacroVariant::isCorrectDataTypeForAction(type, typeid(std::remove_cv<PREFIX TYPE POINTER>))); \ | |
} \ | |
MacroVariant(MacroVariantType type, PREFIX TYPE POINTER&& value) : type(type), NAME(std::move(value)) \ | |
{ \ | |
assert(MacroVariant::isCorrectDataTypeForAction(type, typeid(std::remove_cv<PREFIX TYPE POINTER>))); \ | |
} | |
CALL_ON_EVERY_DATA_TYPE(CREATE_CONSTRUCTOR) | |
#undef CREATE_CONSTRUCTOR | |
MacroVariantType getType() const { return this->type; } | |
#define CREATE_UNION_GETTER(PREFIX, TYPE, POINTER, NAME) \ | |
PREFIX TYPE POINTER const& get ## TYPE() const \ | |
{ \ | |
assert(MacroVariant::isCorrectDataTypeForAction(this->type, typeid(std::remove_cv<PREFIX TYPE POINTER>))); \ | |
return this->NAME; \ | |
} \ | |
PREFIX TYPE POINTER& get ## TYPE() \ | |
{ \ | |
assert(MacroVariant::isCorrectDataTypeForAction(this->type, typeid(std::remove_cv<PREFIX TYPE POINTER>))); \ | |
return this->NAME; \ | |
} | |
CALL_ON_EVERY_DATA_TYPE(CREATE_UNION_GETTER) | |
#undef CREATE_UNION_GETTER | |
bool empty() const { return this->type == MacroVariantType::Nothing; } | |
void clear(); | |
MacroVariant& operator=(MacroVariant&& other) noexcept; | |
MacroVariant& operator=(const MacroVariant& other); | |
private: | |
void destroyValue(); | |
void initValue(); | |
void emplaceConstructFrom(const MacroVariant& other); | |
void emplaceConstructFrom(MacroVariant&& other) noexcept; | |
MacroVariantType type; | |
union | |
{ | |
#define CREATE_UNION_DATA_TYPE(PREFIX, TYPE, POINTER, NAME) \ | |
PREFIX TYPE POINTER NAME; | |
CALL_ON_EVERY_DATA_TYPE(CREATE_UNION_DATA_TYPE) | |
#undef CREATE_UNION_DATA_TYPE | |
}; | |
}; | |
static_assert(std::is_move_assignable<MacroVariant>::value); | |
static_assert(std::is_move_constructible<MacroVariant>::value); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment