I made a triple-type container, that is, a single type that can store a value, under one of the three types used. It's somewhat similar to Boost::Variant.
The header file (multitype.hpp):
#ifndef MULTITYPE_HPP
#define MULTITYPE_HPP
#include <iostream>
#include <cstdlib>
#include <typeinfo>
typedef void* vp_t; // Void pointer (can contain every type)
template <typename _A,typename _B> struct is_same_type { const static bool value = false; };
template <typename _A> struct is_same_type<_A,_A> { const static bool value = true; };
template <class A,class B,class C>
class TripleType
{
protected:
enum ct_t { _tA, _tB, _tC, _init_ }; // Type flags
struct abc_t
{
A __a; // A container
B __b; // B container
C __c; // C container
ct_t _e; // Which type is the current one?
};
private:
abc_t val;
public:
TripleType()
{
(this->val)._e = _init_;
}
template <class T> TripleType(T x)
{
vp_t yv; yv = &x;
bool is_A = is_same_type<T,A>::value;
bool is_B = is_same_type<T,B>::value;
bool is_C = is_same_type<T,C>::value;
if (is_A) { A *t = static_cast<A*>(yv); val.__a = *t; val._e = _tA; }
else if (is_B) { B *t = static_cast<B*>(yv); val.__b = *t; val._e = _tB; }
else if (is_C) { C *t = static_cast<C*>(yv); val.__c = *t; val._e = _tC; }
}
template <class T> TripleType& operator=(T rhs)
{
vp_t yv = &rhs;
bool is_A = is_same_type<T,A>::value;
bool is_B = is_same_type<T,B>::value;
bool is_C = is_same_type<T,C>::value;
if (is_A) { A *t = static_cast<A*>(yv); (this->val).__a = *t; (this->val)._e = _tA; }
else if (is_B) { B *t = static_cast<B*>(yv); (this->val).__b = *t; (this->val)._e = _tB; }
else if (is_C) { C *t = static_cast<C*>(yv); (this->val).__c = *t; (this->val)._e = _tC; }
return *this;
}
template <class T> T get()
{
vp_t yv;
bool is_A = is_same_type<T,A>::value;
bool is_B = is_same_type<T,B>::value;
bool is_C = is_same_type<T,C>::value;
if (is_A) yv = &(val.__a);
else if (is_B) yv = &(val.__b);
else if (is_C) yv = &(val.__c);
T *t = static_cast<T*>(yv);
return *t;
}
const std::type_info& current_type()
{
if ((this->val)._e == _tA)
return typeid(A);
else if ((this->val)._e == _tB)
return typeid(B);
else if ((this->val)._e == _tC)
return typeid(C);
}
};
#endif
Here is an usage example:
#include <iostream>
#include <cstdlib>
#include <string>
#include "multitype.hpp" // The header file where I wrote the mentioned container
using namespace std;
int main()
{
srand(time(NULL));
TripleType<int,string,float> test;
test = rand();
cout << test.get<int>() << endl;
test = string("TripleType test");
cout << test.get<string>() << endl;
test = float(1.6108);
cout << test.get<float>() << endl;
test = 2016;
cout << test.get<int>() << endl;
test = string("Bye.");
cout << test.get<string>() << endl;
}
Any improvements, suggestions, etc. are welcome.
union
than astruct
. That's how you get the space savings. \$\endgroup\$