#include <iostream>
#include <array>
#include <limits>
#include <string>
#include <tuple>
#include <vector>
#include <functional>
template<class Tx, class ... Tr> class VariantIndex;
template<class Tx> class VariantIndex<Tx>
{
public:
private:
};
template<class Tx, class ... Tr> class VariantIndex<Tx, Tx, Tr ...>
{
public:
static constexpr std::size_t index = 1;
private:
};
template<class Tx, class Ty, class ... Tr> class VariantIndex<Tx, Ty, Tr ...>
{
public:
static constexpr std::size_t index = VariantIndex<Tx, Tr ...>::index + 1;
private:
};
template<class ... Tl>
class Variant
{
public:
Variant()
: m_Type(0)
, m_Deleter(nullptr)
, m_Data(nullptr)
{
}
~Variant()
{
if(m_Type && m_Deleter && m_Data)
{
m_Deleter(m_Data);
}
else
{
if(m_Type || m_Deleter || m_Data)
{
//LOG << "Type, deleter and data must be set together.";
}
}
}
template<class T> static Variant MakeByType(const T& t)
{
return Make<VariantIndex<T, Tl ...>::index, T>(t);
}
std::size_t m_Type; ///< Index of type.
std::function<void(void*)> m_Deleter; ///<
void *m_Data; ///< Pointer to data.
template<class T> bool IsType() const
{
return m_Type == VariantIndex<T, Tl ...>::index;
}
template<class T> const T& GetType() const
{
return *reinterpret_cast<const T*>(m_Data);
}
private:
template<std::size_t I, class T> static Variant Make(const T& t)
{
return Variant(I, [](void *ptr){ std::cout << "Delete type " << I << std::endl; delete reinterpret_cast<T*>(ptr); }, new T(t));
}
Variant(std::size_t type, std::function<void(void*)>&& deleter, void *data)
: m_Type(type)
, m_Deleter(std::move(deleter))
, m_Data(data)
{
}
};
typedef Variant<int, std::string, char> TestVar;
int main(int,char**)
{
TestVar v = TestVar::MakeByType<int>('a');
std::cout << v.m_Type << std::endl;
if(v.IsType<int>())
{
std::cout << "int: " << v.GetType<int>() << std::endl;
}
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8YXJyYXk+CiNpbmNsdWRlIDxsaW1pdHM+CiNpbmNsdWRlIDxzdHJpbmc+CiNpbmNsdWRlIDx0dXBsZT4KI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiAKICAgICAgICB0ZW1wbGF0ZTxjbGFzcyBUeCwgY2xhc3MgLi4uIFRyPiBjbGFzcyBWYXJpYW50SW5kZXg7CiAKICAgICAgICAgICAgICAgIHRlbXBsYXRlPGNsYXNzIFR4PiBjbGFzcyBWYXJpYW50SW5kZXg8VHg+CiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBwdWJsaWM6CiAgICAgICAgICAgICAgICBwcml2YXRlOgogICAgICAgICAgICAgICAgfTsKIAogICAgICAgICAgICAgICAgdGVtcGxhdGU8Y2xhc3MgVHgsIGNsYXNzIC4uLiBUcj4gY2xhc3MgVmFyaWFudEluZGV4PFR4LCBUeCwgVHIgLi4uPgogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgcHVibGljOgogICAgICAgICAgICAgICAgICAgICAgICBzdGF0aWMgY29uc3RleHByIHN0ZDo6c2l6ZV90IGluZGV4ID0gMTsKICAgICAgICAgICAgICAgIHByaXZhdGU6CiAgICAgICAgICAgICAgICB9OwogCiAgICAgICAgICAgICAgICB0ZW1wbGF0ZTxjbGFzcyBUeCwgY2xhc3MgVHksIGNsYXNzIC4uLiBUcj4gY2xhc3MgVmFyaWFudEluZGV4PFR4LCBUeSwgVHIgLi4uPgogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgcHVibGljOgogICAgICAgICAgICAgICAgICAgICAgICBzdGF0aWMgY29uc3RleHByIHN0ZDo6c2l6ZV90IGluZGV4ID0gVmFyaWFudEluZGV4PFR4LCBUciAuLi4+OjppbmRleCArIDE7CiAgICAgICAgICAgICAgICBwcml2YXRlOgogICAgICAgICAgICAgICAgfTsKIAogICAgICAgICAgICAgICAgdGVtcGxhdGU8Y2xhc3MgLi4uIFRsPgogICAgICAgICAgICAgICAgY2xhc3MgVmFyaWFudAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgcHVibGljOgogICAgICAgICAgICAgICAgICAgICAgICBWYXJpYW50KCkKICAgICAgICAgICAgICAgICAgICAgICAgOiBtX1R5cGUoMCkKICAgICAgICAgICAgICAgICAgICAgICAgLCBtX0RlbGV0ZXIobnVsbHB0cikKICAgICAgICAgICAgICAgICAgICAgICAgLCBtX0RhdGEobnVsbHB0cikKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICB9CiAKICAgICAgICAgICAgICAgICAgICAgICAgflZhcmlhbnQoKQogICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYobV9UeXBlICYmIG1fRGVsZXRlciAmJiBtX0RhdGEpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbV9EZWxldGVyKG1fRGF0YSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihtX1R5cGUgfHwgbV9EZWxldGVyIHx8IG1fRGF0YSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9MT0cgPDwgIlR5cGUsIGRlbGV0ZXIgYW5kIGRhdGEgbXVzdCBiZSBzZXQgdG9nZXRoZXIuIjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KIAogICAgCQl0ZW1wbGF0ZTxjbGFzcyBUPiBzdGF0aWMgVmFyaWFudCBNYWtlQnlUeXBlKGNvbnN0IFQmIHQpCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gTWFrZTxWYXJpYW50SW5kZXg8VCwgVGwgLi4uPjo6aW5kZXgsIFQ+KHQpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHN0ZDo6c2l6ZV90IG1fVHlwZTsgLy8vPCBJbmRleCBvZiB0eXBlLgogICAgICAgICAgICAgICAgICAgICAgICBzdGQ6OmZ1bmN0aW9uPHZvaWQodm9pZCopPiBtX0RlbGV0ZXI7IC8vLzwgCiAgICAgICAgICAgICAgICAgICAgICAgIHZvaWQgKm1fRGF0YTsgLy8vPCBQb2ludGVyIHRvIGRhdGEuCgoJCQl0ZW1wbGF0ZTxjbGFzcyBUPiBib29sIElzVHlwZSgpIGNvbnN0CgkJCXsKCQkJCXJldHVybiBtX1R5cGUgPT0gVmFyaWFudEluZGV4PFQsIFRsIC4uLj46OmluZGV4OwoJCQl9CgoJCQl0ZW1wbGF0ZTxjbGFzcyBUPiBjb25zdCBUJiBHZXRUeXBlKCkgY29uc3QKCQkJewoJCQkJcmV0dXJuICpyZWludGVycHJldF9jYXN0PGNvbnN0IFQqPihtX0RhdGEpOwoJCQl9CiAgICAgICAgICAgICAgICBwcml2YXRlOgoJCQl0ZW1wbGF0ZTxzdGQ6OnNpemVfdCBJLCBjbGFzcyBUPiBzdGF0aWMgVmFyaWFudCBNYWtlKGNvbnN0IFQmIHQpCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gVmFyaWFudChJLCBbXSh2b2lkICpwdHIpeyBzdGQ6OmNvdXQgPDwgIkRlbGV0ZSB0eXBlICIgPDwgSSA8PCBzdGQ6OmVuZGw7IGRlbGV0ZSByZWludGVycHJldF9jYXN0PFQqPihwdHIpOyB9LCBuZXcgVCh0KSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgVmFyaWFudChzdGQ6OnNpemVfdCB0eXBlLCBzdGQ6OmZ1bmN0aW9uPHZvaWQodm9pZCopPiYmIGRlbGV0ZXIsIHZvaWQgKmRhdGEpCiAgICAgICAgICAgICAgICAgICAgICAgIDogbV9UeXBlKHR5cGUpCiAgICAgICAgICAgICAgICAgICAgICAgICwgbV9EZWxldGVyKHN0ZDo6bW92ZShkZWxldGVyKSkKICAgICAgICAgICAgICAgICAgICAgICAgLCBtX0RhdGEoZGF0YSkKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9OwogCiAgICAgICAgCnR5cGVkZWYgVmFyaWFudDxpbnQsIHN0ZDo6c3RyaW5nLCBjaGFyPiBUZXN0VmFyOwogCmludCBtYWluKGludCxjaGFyKiopCnsKICAgIFRlc3RWYXIgdiA9IFRlc3RWYXI6Ok1ha2VCeVR5cGU8aW50PignYScpOwogICAgc3RkOjpjb3V0IDw8IHYubV9UeXBlIDw8IHN0ZDo6ZW5kbDsKICAgIGlmKHYuSXNUeXBlPGludD4oKSkKICAgIHsKICAgIAlzdGQ6OmNvdXQgPDwgImludDogIiA8PCB2LkdldFR5cGU8aW50PigpIDw8IHN0ZDo6ZW5kbDsKICAgIH0KICAgIHJldHVybiAwOwp9