Commit 52f2a0ff authored by Davis King's avatar Davis King

Upgraded the type_safe_union with a constructor and assignment operator

which can copy an object into the type safe union.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%404269
parent 5e7fe6a2
...@@ -18,6 +18,12 @@ namespace ...@@ -18,6 +18,12 @@ namespace
logger dlog("test.type_safe_union"); logger dlog("test.type_safe_union");
struct can_not_copy: noncopyable {};
void serialize(const can_not_copy&, std::ostream&) {}
void deserialize(can_not_copy&, std::istream&) {}
void swap(can_not_copy&, can_not_copy&) {}
class test class test
{ {
...@@ -294,6 +300,115 @@ namespace ...@@ -294,6 +300,115 @@ namespace
DLIB_TEST(b.is_empty() == true); DLIB_TEST(b.is_empty() == true);
} }
{
type_safe_union<char, float, std::string> a, b, empty_union;
ostringstream sout;
istringstream sin;
a = 'd';
serialize(a, sout);
sin.str(sout.str());
deserialize(b, sin);
DLIB_TEST(b.contains<int>() == false);
DLIB_TEST(b.contains<float>() == false);
DLIB_TEST(b.contains<char>() == true);
DLIB_TEST(b.get<char>() == 'd');
DLIB_TEST(a.contains<int>() == false);
DLIB_TEST(a.contains<float>() == false);
DLIB_TEST(a.contains<char>() == true);
DLIB_TEST(a.get<char>() == 'd');
sin.clear();
sout.clear();
sout.str("");
a = std::string("davis");
serialize(a, sout);
sin.str(sout.str());
deserialize(b, sin);
DLIB_TEST(b.contains<int>() == false);
DLIB_TEST(b.contains<float>() == false);
DLIB_TEST(b.contains<std::string>() == true);
DLIB_TEST(b.get<std::string>() == "davis");
sin.clear();
sout.clear();
sout.str("");
serialize(empty_union, sout);
sin.str(sout.str());
deserialize(b, sin);
DLIB_TEST(b.is_empty() == true);
}
{
typedef type_safe_union<char, float, std::string, can_not_copy> tsu_type;
tsu_type a('d'), aa(std::string("davis")), b, empty_union;
ostringstream sout;
istringstream sin;
serialize(a, sout);
sin.str(sout.str());
deserialize(b, sin);
DLIB_TEST(b.contains<int>() == false);
DLIB_TEST(b.contains<float>() == false);
DLIB_TEST(b.contains<char>() == true);
DLIB_TEST(b.get<char>() == 'd');
DLIB_TEST(a.contains<int>() == false);
DLIB_TEST(a.contains<float>() == false);
DLIB_TEST(a.contains<char>() == true);
DLIB_TEST(a.get<char>() == 'd');
DLIB_TEST(aa.contains<int>() == false);
DLIB_TEST(aa.contains<float>() == false);
DLIB_TEST(aa.contains<char>() == false);
DLIB_TEST(aa.contains<std::string>() == true);
sin.clear();
sout.clear();
sout.str("");
serialize(aa, sout);
sin.str(sout.str());
deserialize(b, sin);
DLIB_TEST(b.contains<int>() == false);
DLIB_TEST(b.contains<float>() == false);
DLIB_TEST(b.contains<std::string>() == true);
DLIB_TEST(b.get<std::string>() == "davis");
sin.clear();
sout.clear();
sout.str("");
serialize(empty_union, sout);
sin.str(sout.str());
deserialize(b, sin);
DLIB_TEST(b.is_empty() == true);
a.get<can_not_copy>();
DLIB_TEST(a.contains<can_not_copy>() == true);
}
} }
}; };
......
...@@ -79,6 +79,38 @@ namespace dlib ...@@ -79,6 +79,38 @@ namespace dlib
// -------------------------------------------- // --------------------------------------------
template <typename T>
void validate_type()
{
// ERROR: You are trying to get a type of object that isn't
// representable by this type_safe_union. I.e. The given
// type T isn't one of the ones given to this object's template
// arguments.
COMPILE_TIME_ASSERT(( is_same_type<T,T1>::value ||
is_same_type<T,T2>::value ||
is_same_type<T,T3>::value ||
is_same_type<T,T4>::value ||
is_same_type<T,T5>::value ||
is_same_type<T,T6>::value ||
is_same_type<T,T7>::value ||
is_same_type<T,T8>::value ||
is_same_type<T,T9>::value ||
is_same_type<T,T10>::value ||
is_same_type<T,T11>::value ||
is_same_type<T,T12>::value ||
is_same_type<T,T13>::value ||
is_same_type<T,T14>::value ||
is_same_type<T,T15>::value ||
is_same_type<T,T16>::value ||
is_same_type<T,T17>::value ||
is_same_type<T,T18>::value ||
is_same_type<T,T19>::value ||
is_same_type<T,T20>::value
));
}
struct destruct_helper struct destruct_helper
{ {
...@@ -115,6 +147,19 @@ namespace dlib ...@@ -115,6 +147,19 @@ namespace dlib
} }
} }
template <typename T>
void construct (
const T& item
)
{
if (type_identity != get_type_id<T>())
{
destruct();
new(mem.get()) T(item);
type_identity = get_type_id<T>();
}
}
template <typename T> template <typename T>
T& unchecked_get( T& unchecked_get(
) )
...@@ -179,6 +224,15 @@ namespace dlib ...@@ -179,6 +224,15 @@ namespace dlib
{ {
} }
template <typename T>
type_safe_union (
const T& item
) : type_identity(0)
{
validate_type<T>();
construct(item);
}
~type_safe_union() ~type_safe_union()
{ {
destruct(); destruct();
...@@ -501,37 +555,14 @@ namespace dlib ...@@ -501,37 +555,14 @@ namespace dlib
T& get( T& get(
) )
{ {
// ERROR: You are trying to get a type of object that isn't validate_type<T>();
// representable by this type_safe_union. I.e. The given
// type T isn't one of the ones given to this object's template
// arguments.
COMPILE_TIME_ASSERT(( is_same_type<T,T1>::value ||
is_same_type<T,T2>::value ||
is_same_type<T,T3>::value ||
is_same_type<T,T4>::value ||
is_same_type<T,T5>::value ||
is_same_type<T,T6>::value ||
is_same_type<T,T7>::value ||
is_same_type<T,T8>::value ||
is_same_type<T,T9>::value ||
is_same_type<T,T10>::value ||
is_same_type<T,T11>::value ||
is_same_type<T,T12>::value ||
is_same_type<T,T13>::value ||
is_same_type<T,T14>::value ||
is_same_type<T,T15>::value ||
is_same_type<T,T16>::value ||
is_same_type<T,T17>::value ||
is_same_type<T,T18>::value ||
is_same_type<T,T19>::value ||
is_same_type<T,T20>::value
));
construct<T>(); construct<T>();
return *reinterpret_cast<T*>(mem.get()); return *reinterpret_cast<T*>(mem.get());
} }
template <typename T>
type_safe_union& operator= ( const T& item) { get<T>() = item; return *this; }
}; };
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -547,6 +578,40 @@ namespace dlib ...@@ -547,6 +578,40 @@ namespace dlib
type_safe_union<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10, T11,T12,T13,T14,T15,T16,T17,T18,T19,T20>& b type_safe_union<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10, T11,T12,T13,T14,T15,T16,T17,T18,T19,T20>& b
) { a.swap(b); } ) { a.swap(b); }
// ----------------------------------------------------------------------------------------
template <
typename from,
typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9, typename T10,
typename T11, typename T12, typename T13, typename T14, typename T15,
typename T16, typename T17, typename T18, typename T19, typename T20
>
struct is_convertible<from,
type_safe_union<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10, T11,T12,T13,T14,T15,T16,T17,T18,T19,T20> >
{
const static bool value = is_convertible<from,T1>::value ||
is_convertible<from,T2>::value ||
is_convertible<from,T3>::value ||
is_convertible<from,T4>::value ||
is_convertible<from,T5>::value ||
is_convertible<from,T6>::value ||
is_convertible<from,T7>::value ||
is_convertible<from,T8>::value ||
is_convertible<from,T9>::value ||
is_convertible<from,T10>::value ||
is_convertible<from,T11>::value ||
is_convertible<from,T12>::value ||
is_convertible<from,T13>::value ||
is_convertible<from,T14>::value ||
is_convertible<from,T15>::value ||
is_convertible<from,T16>::value ||
is_convertible<from,T17>::value ||
is_convertible<from,T18>::value ||
is_convertible<from,T19>::value ||
is_convertible<from,T20>::value;
};
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
} }
......
...@@ -89,6 +89,19 @@ namespace dlib ...@@ -89,6 +89,19 @@ namespace dlib
- this object is properly initialized - this object is properly initialized
!*/ !*/
template <typename T>
type_safe_union (
const T& item
);
/*!
requires
- T must be one of the types given to this object's template arguments
ensures
- this object is properly initialized
- #get<T>() == item
(i.e. this object will contain a copy of item)
!*/
~type_safe_union( ~type_safe_union(
); );
/*! /*!
...@@ -211,6 +224,19 @@ namespace dlib ...@@ -211,6 +224,19 @@ namespace dlib
- returns a non-const reference to the newly created T object. - returns a non-const reference to the newly created T object.
!*/ !*/
template <typename T>
type_safe_union& operator= (
const T& item
);
/*!
requires
- T must be one of the types given to this object's template arguments
ensures
- #get<T>() == item
(i.e. this object will contain a copy of item)
- returns *this
!*/
void swap ( void swap (
type_safe_union& item type_safe_union& item
); );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment