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