Commit 63052d26 authored by Dominik Charousset's avatar Dominik Charousset

Port variant to the new sum type API

parent e60d7bc2
...@@ -22,8 +22,11 @@ ...@@ -22,8 +22,11 @@
#include <type_traits> #include <type_traits>
#include "caf/config.hpp" #include "caf/config.hpp"
#include "caf/default_sum_type_access.hpp"
#include "caf/fwd.hpp" #include "caf/fwd.hpp"
#include "caf/static_visitor.hpp" #include "caf/static_visitor.hpp"
#include "caf/sum_type.hpp"
#include "caf/sum_type_access.hpp"
#include "caf/meta/omittable.hpp" #include "caf/meta/omittable.hpp"
...@@ -36,13 +39,6 @@ ...@@ -36,13 +39,6 @@
return f(std::forward<Us>(xs)..., \ return f(std::forward<Us>(xs)..., \
x.get(std::integral_constant<int, (n <= max_type_id ? n : 0)>())) x.get(std::integral_constant<int, (n <= max_type_id ? n : 0)>()))
#define CAF_VARIANT_DISPATCH_CASE(n) \
case n: \
return next.template apply_impl<Result>( \
std::forward<Variant>(next), std::forward<Visitor>(f), \
std::forward<Us>(xs)..., \
x.get(std::integral_constant<int, (n <= max_type_id ? n : 0)>()))
#define CAF_VARIANT_ASSIGN_CASE(n) \ #define CAF_VARIANT_ASSIGN_CASE(n) \
case n: { \ case n: { \
using tmp_t = typename detail::tl_at< \ using tmp_t = typename detail::tl_at< \
...@@ -57,10 +53,6 @@ namespace caf { ...@@ -57,10 +53,6 @@ namespace caf {
constexpr size_t variant_npos = static_cast<size_t>(-1); constexpr size_t variant_npos = static_cast<size_t>(-1);
struct variant_marker_t {};
constexpr variant_marker_t variant_marker = variant_marker_t{};
template <class T> template <class T>
struct is_variant : std::false_type {}; struct is_variant : std::false_type {};
...@@ -190,6 +182,15 @@ public: ...@@ -190,6 +182,15 @@ public:
} }
/// @cond PRIVATE /// @cond PRIVATE
inline variant& data() {
return *this;
}
inline const variant& data() const {
return *this;
}
template <int Pos> template <int Pos>
bool is(std::integral_constant<int, Pos>) const { bool is(std::integral_constant<int, Pos>) const {
return type_ == Pos; return type_ == Pos;
...@@ -219,17 +220,17 @@ public: ...@@ -219,17 +220,17 @@ public:
template <class Result, class Visitor, class... Variants> template <class Result, class Visitor, class... Variants>
Result apply(Visitor&& visitor, Variants&&... xs) const { Result apply(Visitor&& visitor, Variants&&... xs) const {
return apply_impl<Result>(*this, std::forward<Visitor>(visitor), return apply_impl<Result>(*this, std::forward<Visitor>(visitor),
std::forward<Variants>(xs)..., variant_marker); std::forward<Variants>(xs)...);
} }
template <class Result, class Visitor, class... Variants> template <class Result, class Visitor, class... Variants>
Result apply(Visitor&& visitor, Variants&&... xs) { Result apply(Visitor&& visitor, Variants&&... xs) {
return apply_impl<Result>(*this, std::forward<Visitor>(visitor), return apply_impl<Result>(*this, std::forward<Visitor>(visitor),
std::forward<Variants>(xs)..., variant_marker); std::forward<Variants>(xs)...);
} }
template <class Result, class Self, class Visitor, class... Us> template <class Result, class Self, class Visitor, class... Us>
static Result apply_impl(Self& x, Visitor&& f, variant_marker_t, Us&&... xs) { static Result apply_impl(Self& x, Visitor&& f, Us&&... xs) {
switch (x.type_) { switch (x.type_) {
default: CAF_RAISE_ERROR("invalid type found"); default: CAF_RAISE_ERROR("invalid type found");
CAF_VARIANT_CASE(0); CAF_VARIANT_CASE(0);
...@@ -255,33 +256,6 @@ public: ...@@ -255,33 +256,6 @@ public:
} }
} }
template <class Result, class Self, class Visitor, class Variant, class... Us>
static detail::enable_if_t<is_variant<Variant>::value, Result>
apply_impl(Self& x, Visitor&& f, Variant&& next, Us&&... xs) {
switch (x.type_) {
default: CAF_RAISE_ERROR("invalid type found");
CAF_VARIANT_DISPATCH_CASE(0);
CAF_VARIANT_DISPATCH_CASE(1);
CAF_VARIANT_DISPATCH_CASE(2);
CAF_VARIANT_DISPATCH_CASE(3);
CAF_VARIANT_DISPATCH_CASE(4);
CAF_VARIANT_DISPATCH_CASE(5);
CAF_VARIANT_DISPATCH_CASE(6);
CAF_VARIANT_DISPATCH_CASE(7);
CAF_VARIANT_DISPATCH_CASE(8);
CAF_VARIANT_DISPATCH_CASE(9);
CAF_VARIANT_DISPATCH_CASE(10);
CAF_VARIANT_DISPATCH_CASE(11);
CAF_VARIANT_DISPATCH_CASE(12);
CAF_VARIANT_DISPATCH_CASE(13);
CAF_VARIANT_DISPATCH_CASE(14);
CAF_VARIANT_DISPATCH_CASE(15);
CAF_VARIANT_DISPATCH_CASE(16);
CAF_VARIANT_DISPATCH_CASE(17);
CAF_VARIANT_DISPATCH_CASE(18);
CAF_VARIANT_DISPATCH_CASE(19);
}
}
/// @endcond /// @endcond
private: private:
...@@ -343,55 +317,14 @@ private: ...@@ -343,55 +317,14 @@ private:
detail::variant_data<typename lift_void<Ts>::type...> data_; detail::variant_data<typename lift_void<Ts>::type...> data_;
}; };
/// Enable `holds_alternative`, `get`, `get_if`, and `visit` for `variant`.
/// @relates variant /// @relates variant
template <class T, class... Us> /// @relates SumType
T& get(variant<Us...>& value) { template <class... Ts>
using namespace detail; struct sum_type_access<variant<Ts...>>
int_token<tl_index_where<type_list<Us...>, : default_sum_type_access<variant<Ts...>> {
tbind<is_same_ish, T>::template type>::value> token; // nop
// silence compiler error about "binding to unrelated types" such as };
// 'signed char' to 'char' (which is obvious bullshit)
return reinterpret_cast<T&>(value.get(token));
}
/// @relates variant
template <class T, class... Us>
const T& get(const variant<Us...>& value) {
// compiler implicitly restores const because of the return type
return get<T>(const_cast<variant<Us...>&>(value));
}
/// @relates variant
template <class T, class... Us>
T* get_if(variant<Us...>* value) {
using namespace detail;
int_token<tl_index_where<type_list<Us...>,
tbind<is_same_ish, T>::template type>::value> token;
if (value->is(token))
return &get<T>(*value);
return nullptr;
}
/// @relates variant
template <class T, class... Us>
const T* get_if(const variant<Us...>* value) {
// compiler implicitly restores const because of the return type
return get_if<T>(const_cast<variant<Us...>*>(value));
}
/// @relates variant
template <class Visitor, class Variant, class... Variants,
class Result = variant_visit_result_t<Visitor, Variant, Variants...>>
detail::enable_if_t<is_variant<Variant>::value, Result>
visit(Visitor&& f, Variant&& x, Variants&&... xs) {
return x.template apply<Result>(std::forward<Visitor>(f),
std::forward<Variants>(xs)...);
}
template <class T, class... Ts>
bool holds_alternative(const variant<Ts...>& data) {
return data.template is<T>();
}
/// @relates variant /// @relates variant
template <class T, template <class> class Predicate> template <class T, template <class> class Predicate>
......
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