Skip to content
Snippets Groups Projects
Commit eb5bd473 authored by Jan Trávníček's avatar Jan Trávníček
Browse files

allow size_t as element of variant

parent 8dc2aca4
No related branches found
No related tags found
No related merge requests found
......@@ -27,47 +27,63 @@ struct static_max<arg1, arg2, others...> {
static_max<arg2, others...>::value;
};
 
struct type_id_hash_code {
size_t m_hash_code;
type_id_hash_code ( size_t hash_code ) : m_hash_code ( hash_code ) {
}
friend bool operator == ( const type_id_hash_code & first, const type_id_hash_code & second ) {
return first.m_hash_code == second.m_hash_code;
}
friend bool operator != ( const type_id_hash_code & first, const type_id_hash_code & second ) {
return first.m_hash_code != second.m_hash_code;
}
};
template<typename... Ts>
struct variant_helper;
 
template<typename F, typename... Ts>
struct variant_helper<F, Ts...> {
inline static void destroy(size_t id, void * data) {
inline static void destroy(type_id_hash_code id, void * data) {
if (id == typeid(F).hash_code())
reinterpret_cast<F*>(data)->~F();
else
variant_helper<Ts...>::destroy(id, data);
}
 
inline static void copy(size_t old_t, const void * old_v, void * new_v) {
inline static void copy(type_id_hash_code old_t, const void * old_v, void * new_v) {
if (old_t == typeid(F).hash_code())
new (new_v) F(*reinterpret_cast<const F*>(old_v));
else
variant_helper<Ts...>::copy(old_t, old_v, new_v);
}
 
inline static void move(size_t old_t, void * old_v, void * new_v) {
inline static void move(type_id_hash_code old_t, void * old_v, void * new_v) {
if (old_t == typeid(F).hash_code())
new (new_v) F(std::move(*reinterpret_cast<F*>(old_v)));
else
variant_helper<Ts...>::move(old_t, old_v, new_v);
}
 
inline static void print(ostream& out, const size_t id, const void* data) {
inline static void print(ostream& out, type_id_hash_code id, const void* data) {
if (id == typeid(F).hash_code())
out << *reinterpret_cast<const F*>(data);
else
variant_helper<Ts...>::print(out, id, data);
}
 
inline static std::string string(const size_t id, const void* data) {
inline static std::string string(type_id_hash_code id, const void* data) {
if (id == typeid(F).hash_code())
return (std::string) *reinterpret_cast<const F*>(data);
else
return variant_helper<Ts...>::string(id, data);
}
 
inline static int compareHelper(size_t this_t, const void * this_v, size_t other_t, const void * other_v) {
inline static int compareHelper(type_id_hash_code this_t, const void * this_v, type_id_hash_code other_t, const void * other_v) {
if (this_t == typeid(F).hash_code() && other_t != typeid(F).hash_code()) return -1;
if (this_t != typeid(F).hash_code() && other_t == typeid(F).hash_code()) return 1;
 
......@@ -81,36 +97,36 @@ struct variant_helper<F, Ts...> {
 
template<typename... Ts>
struct variant_helper<void, Ts...> {
inline static void destroy(size_t id, void * data) {
inline static void destroy(type_id_hash_code id, void * data) {
if (id != typeid(void).hash_code())
variant_helper<Ts...>::destroy(id, data);
}
 
inline static void copy(size_t old_t, const void * old_v, void * new_v) {
inline static void copy(type_id_hash_code old_t, const void * old_v, void * new_v) {
if (old_t != typeid(void).hash_code())
variant_helper<Ts...>::copy(old_t, old_v, new_v);
}
 
inline static void move(size_t old_t, void * old_v, void * new_v) {
inline static void move(type_id_hash_code old_t, void * old_v, void * new_v) {
if (old_t != typeid(void).hash_code())
variant_helper<Ts...>::move(old_t, old_v, new_v);
}
 
inline static void print(ostream& out, const size_t id, const void* data) {
inline static void print(ostream& out, type_id_hash_code id, const void* data) {
if (id == typeid(void).hash_code())
out << "void";
else
variant_helper<Ts...>::print(out, id, data);
}
 
inline static std::string string(const size_t id, const void* data) {
inline static std::string string(type_id_hash_code id, const void* data) {
if (id == typeid(void).hash_code())
return "void";
else
return variant_helper<Ts...>::string(id, data);
}
 
inline static int compareHelper(size_t this_t, const void * this_v, size_t other_t, const void * other_v) {
inline static int compareHelper(type_id_hash_code this_t, const void * this_v, type_id_hash_code other_t, const void * other_v) {
if (this_t == typeid(void).hash_code() && other_t != typeid(void).hash_code()) return -1;
if (this_t != typeid(void).hash_code() && other_t == typeid(void).hash_code()) return 1;
 
......@@ -122,12 +138,12 @@ struct variant_helper<void, Ts...> {
};
 
template<> struct variant_helper<> {
inline static void destroy(size_t, void *) { }
inline static void copy(size_t, const void *, void *) { }
inline static void move(size_t, void *, void *) { }
inline static void print(ostream&, const size_t, const void *) {}
inline static std::string string(const size_t, const void *) { return ""; }
inline static int compareHelper(size_t, const void *, size_t, const void *) { return 0; }
inline static void destroy(type_id_hash_code, void *) { }
inline static void copy(type_id_hash_code, const void *, void *) { }
inline static void move(type_id_hash_code, void *, void *) { }
inline static void print(ostream&, type_id_hash_code, const void *) {}
inline static std::string string(type_id_hash_code, const void *) { return ""; }
inline static int compareHelper(type_id_hash_code, const void *, type_id_hash_code, const void *) { return 0; }
};
 
template<typename ST, typename AT, typename... Ts>
......@@ -141,10 +157,10 @@ class variant_base<ST, AT> {
using data_t = typename std::aligned_storage<data_size, data_align>::type;
 
protected:
size_t type_id;
type_id_hash_code type_id;
data_t data;
 
variant_base( size_t id ) : type_id ( id ) { }
variant_base( type_id_hash_code id ) : type_id ( id ) { }
};
 
template<typename ST, typename AT, typename F, typename... Ts>
......@@ -152,11 +168,11 @@ class variant_base<ST, AT, F, Ts...> : public variant_base<ST, AT, Ts...> {
using variant_base<ST, AT, Ts...>::variant_base;
 
protected:
variant_base( size_t type_id ) : variant_base<ST, AT, Ts...>::variant_base ( type_id ) { }
variant_base( type_id_hash_code type_id ) : variant_base<ST, AT, Ts...>::variant_base ( type_id ) { }
 
public:
variant_base(const F& value) : variant_base<ST, AT, Ts...>::variant_base ( typeid(F).hash_code() ) { new (&this->data) F(value); }
variant_base(F&& value) : variant_base<ST, AT, Ts...>::variant_base ( typeid(F).hash_code() ) { new (&this->data) F(std::move(value)); }
variant_base(const F& value) : variant_base<ST, AT, Ts...>::variant_base ( type_id_hash_code ( typeid(F).hash_code() ) ) { new (&this->data) F(value); }
variant_base(F&& value) : variant_base<ST, AT, Ts...>::variant_base ( type_id_hash_code ( typeid(F).hash_code() ) ) { new (&this->data) F(std::move(value)); }
 
variant_base() : variant_base<ST, AT, Ts ... >::variant_base ( ) { }
};
......@@ -166,10 +182,10 @@ class variant_base<ST, AT, void, Ts...> : public variant_base<ST, AT, Ts...> {
using variant_base<ST, AT, Ts...>::variant_base;
 
protected:
variant_base( size_t type_id ) : variant_base<ST, AT, Ts...>::variant_base ( type_id ) { }
variant_base( type_id_hash_code type_id ) : variant_base<ST, AT, Ts...>::variant_base ( type_id ) { }
 
public:
variant_base() : variant_base<ST, AT, Ts...>::variant_base ( typeid(void).hash_code() ) { }
variant_base() : variant_base<ST, AT, Ts...>::variant_base ( type_id_hash_code ( typeid(void).hash_code() ) ) { }
};
 
template<class T>
......
......@@ -158,3 +158,13 @@ void VariantTest::testVariantSameTypes() {
 
CPPUNIT_ASSERT ( v1.is < int > ( ) );
}
void VariantTest::testSizeT() {
std::variant < size_t, int, void > a ( ( size_t ) 1 );
std::variant < size_t, int, void > b ( 1 );
std::variant < size_t, int, void > c;
CPPUNIT_ASSERT ( a.is < size_t > ( ) );
CPPUNIT_ASSERT ( b.is < int > ( ) );
CPPUNIT_ASSERT ( c.is < void > ( ) );
}
......@@ -13,6 +13,7 @@ class VariantTest : public CppUnit::TestFixture
CPPUNIT_TEST( testVariantVoid );
CPPUNIT_TEST( testVariantDefault );
CPPUNIT_TEST( testVariantSameTypes );
CPPUNIT_TEST( testSizeT );
CPPUNIT_TEST_SUITE_END();
 
public:
......@@ -74,6 +75,7 @@ public:
void testVariantVoid();
void testVariantDefault();
void testVariantSameTypes();
void testSizeT();
};
 
namespace std {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment