Commit 2ab72626 authored by Dominik Charousset's avatar Dominik Charousset

implemented proper operator= for optional_variant

parent 3bba38ed
......@@ -56,6 +56,12 @@ struct lift_void { typedef T type; };
template<>
struct lift_void<void> { typedef util::void_type type; };
template<typename T>
struct unlift_void { typedef T type; };
template<>
struct unlift_void<util::void_type> { typedef void type; };
template<typename T0, typename T1 = util::void_type,
typename T2 = util::void_type, typename T3 = util::void_type,
typename T4 = util::void_type, typename T5 = util::void_type,
......@@ -70,11 +76,6 @@ struct optional_variant_data {
optional_variant_data() { }
template<int Id, typename U>
optional_variant_data(std::integral_constant<int, Id> token, U&& arg) {
cr(get(token), std::forward<U>(arg));
}
~optional_variant_data() { }
CPPA_OPTIONAL_VARIANT_DATA_GETTER(0)
......
......@@ -36,6 +36,7 @@
#include "cppa/util/type_list.hpp"
#include "cppa/util/void_type.hpp"
#include "cppa/util/type_traits.hpp"
#include "cppa/detail/optional_variant_data.hpp"
......@@ -67,35 +68,26 @@ class optional_variant {
static constexpr int void_pos = util::tl_find<types, void>::value;
template<typename U>
/**
* @brief Checks whether this objects holds a value of type @p T.
*/
template<typename T>
inline bool is() const {
static_assert(util::tl_find<types, U>::value != -1, "invalid type");
return m_type == util::tl_find<types, U>::value;
return m_type != -1 && m_type == util::tl_find<types, T>::value;
}
template<typename U>
optional_variant& operator=(const U& arg) {
static_assert(util::tl_find<types, U>::value != -1, "invalid type");
optional_variant& operator=(U&& arg) {
destroy_data();
m_type = util::tl_find<types, U>::value;
auto& ref = get(make_int_token<util::tl_find<types, U>::value>());
new (&ref) U (arg);
set(std::forward<U>(arg));
return *this;
}
optional_variant() : m_type(-1) { }
template<typename U>
optional_variant(const U& value)
: m_type{util::tl_find<types, U>::value}
, m_data{std::integral_constant<int, util::tl_find<types, U>::value>{}, value} {
static_assert(util::tl_find<types, U>::value >= 0, "invalid type");
}
optional_variant(const util::void_type& value)
: m_type{void_pos}
, m_data{std::integral_constant<int, void_pos>{}, value} {
static_assert(void_pos >= 0, "this variant does not allow 'void' value");
optional_variant(U&& arg) {
set(std::forward<U>(arg));
}
~optional_variant() {
......@@ -105,10 +97,17 @@ class optional_variant {
/**
* @brief Checks whether this optional_variant is valid.
*/
explicit operator bool() const {
inline explicit operator bool() const {
return m_type != -1;
}
/**
* @brief Checks whether this optional_variant is invalid.
*/
inline bool operator!() const {
return m_type == -1;
}
/** @cond PRIVATE */
template<int Pos>
......@@ -196,6 +195,22 @@ class optional_variant {
apply(detail::optional_variant_data_destructor{});
}
template<typename U>
typename std::enable_if<
!std::is_same<typename util::rm_const_and_ref<U>::type, none_t>::value
>::type
set(U&& arg) {
typedef typename util::rm_const_and_ref<U>::type stripped_type;
typedef typename detail::unlift_void<stripped_type>::type type;
static constexpr int type_id = util::tl_find<types, type>::value;
static_assert(type_id != -1, "invalid type");
m_type = type_id;
auto& ref = m_data.get(make_int_token<type_id>());
new (&ref) stripped_type (std::forward<U>(arg));
}
inline void set(const none_t&) { m_type = -1; }
int m_type;
detail::optional_variant_data<typename detail::lift_void<Ts>::type...> m_data;
......
......@@ -85,7 +85,10 @@ int main() {
CPPA_CHECK_EQUAL(apply_visitor(dv, t4), static_cast<double>(2.3f));
t4 = 1;
CPPA_CHECK(t4.is<int>() && get<int>(t4) == 1);
CPPA_CHECK(t4 && t4.is<int>() && get<int>(t4) == 1);
t4 = none_t{};
CPPA_CHECK(!t4);
}
/* run tests using user-defined types */ {
......
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