Commit 2b4734b9 authored by Dominik Charousset's avatar Dominik Charousset Committed by Joseph Noir

Handle `optional<T>` members in `announce()`

parent 0a86b71c
......@@ -30,9 +30,9 @@
#include "caf/deserializer.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/detail/types_array.hpp"
#include "caf/detail/abstract_uniform_type_info.hpp"
#include "caf/detail/types_array.hpp"
namespace caf {
namespace detail {
......@@ -48,11 +48,9 @@ long sfinae_has_push_back(void*); // SFNINAE default
template <class T>
struct is_stl_compliant_list {
static constexpr bool value =
detail::is_iterable<T>::value &&
sizeof(sfinae_has_push_back(static_cast<T*>(nullptr))) == sizeof(char);
detail::is_iterable<T>::value
&& sizeof(sfinae_has_push_back(static_cast<T*>(nullptr))) == sizeof(char);
};
// check if there's an 'insert' that takes a C::value_type
......@@ -64,40 +62,46 @@ long sfinae_has_insert(void*); // SFNINAE default
template <class T>
struct is_stl_compliant_map {
static constexpr bool value =
detail::is_iterable<T>::value &&
sizeof(sfinae_has_insert(static_cast<T*>(nullptr))) == sizeof(char);
detail::is_iterable<T>::value
&& sizeof(sfinae_has_insert(static_cast<T*>(nullptr))) == sizeof(char);
};
template <class T>
struct is_stl_pair : std::false_type {};
struct is_stl_pair : std::false_type {
// no members
};
template <class F, typename S>
struct is_stl_pair<std::pair<F, S>> : std::true_type {};
struct is_stl_pair<std::pair<F, S>> : std::true_type {
// no members
};
using primitive_impl = std::integral_constant<int, 0>;
using list_impl = std::integral_constant<int, 1>;
using map_impl = std::integral_constant<int, 2>;
using pair_impl = std::integral_constant<int, 3>;
using opt_impl = std::integral_constant<int, 4>;
using recursive_impl = std::integral_constant<int, 9>;
template <class T>
constexpr int impl_id() {
return detail::is_primitive<T>::value ?
0 :
(is_stl_compliant_list<T>::value ?
1 :
(is_stl_compliant_map<T>::value ?
2 :
(is_stl_pair<T>::value ? 3 : 9)));
return detail::is_primitive<T>::value
? 0
: (is_stl_compliant_list<T>::value
? 1
: (is_stl_compliant_map<T>::value
? 2
: (is_stl_pair<T>::value
? 3
: (detail::is_optional<T>::value
? 4
: 9))));
}
template <class T>
struct deconst_pair {
using type = T;
};
template <class K, typename V>
......@@ -105,13 +109,10 @@ struct deconst_pair<std::pair<K, V>> {
using first_type = typename std::remove_const<K>::type;
using second_type = typename std::remove_const<V>::type;
using type = std::pair<first_type, second_type>;
};
class default_serialize_policy {
public:
template <class T>
void operator()(const T& val, serializer* s) const {
std::integral_constant<int, impl_id<T>()> token;
......@@ -122,11 +123,9 @@ class default_serialize_policy {
void operator()(T& val, deserializer* d) const {
std::integral_constant<int, impl_id<T>()> token;
dimpl(val, d, token);
// static_types_array<T>::arr[0]->deserialize(&val, d);
}
private:
template <class T>
void simpl(const T& val, serializer* s, primitive_impl) const {
s->write_value(val);
......@@ -154,6 +153,15 @@ class default_serialize_policy {
(*this)(val.second, s);
}
template <class T>
void simpl(const optional<T>& val, serializer* s, opt_impl) const {
uint8_t flag = val ? 1 : 0;
s->write_value(flag);
if (val) {
(*this)(*val, s);
}
}
template <class T>
void simpl(const T& val, serializer* s, recursive_impl) const {
static_types_array<T>::arr[0]->serialize(&val, s);
......@@ -195,19 +203,30 @@ class default_serialize_policy {
(*this)(storage.second, d);
}
template <class T>
void dimpl(optional<T>& val, deserializer* d, opt_impl) const {
auto flag = d->read<uint8_t>();
if (flag != 0) {
T tmp;
(*this)(tmp, d);
val = std::move(tmp);
} else {
val = none;
}
}
template <class T>
void dimpl(T& storage, deserializer* d, recursive_impl) const {
static_types_array<T>::arr[0]->deserialize(&storage, d);
}
};
class forwarding_serialize_policy {
public:
inline forwarding_serialize_policy(uniform_type_info_ptr uti)
: m_uti(std::move(uti)) {}
: m_uti(std::move(uti)) {
// nop
}
template <class T>
void operator()(const T& val, serializer* s) const {
......@@ -220,9 +239,7 @@ class forwarding_serialize_policy {
}
private:
uniform_type_info_ptr m_uti;
};
template <class T, class AccessPolicy,
......@@ -230,15 +247,17 @@ template <class T, class AccessPolicy,
bool IsEnum = std::is_enum<T>::value,
bool IsEmptyType = std::is_class<T>::value&& std::is_empty<T>::value>
class member_tinfo : public detail::abstract_uniform_type_info<T> {
public:
member_tinfo(AccessPolicy apol, SerializePolicy spol)
: m_apol(std::move(apol)), m_spol(std::move(spol)) {}
: m_apol(std::move(apol)), m_spol(std::move(spol)) {
// nop
}
member_tinfo(AccessPolicy apol) : m_apol(std::move(apol)) {}
member_tinfo(AccessPolicy apol) : m_apol(std::move(apol)) {
// nop
}
member_tinfo() {}
member_tinfo() = default;
void serialize(const void* vptr, serializer* s) const override {
m_spol(m_apol(vptr), s);
......@@ -278,9 +297,7 @@ class member_tinfo<T, A, S, false, true>
// nop
}
member_tinfo() {
// nop
}
member_tinfo() = default;
void serialize(const void*, serializer*) const override {
// nop
......@@ -294,16 +311,15 @@ class member_tinfo<T, A, S, false, true>
template <class T, class AccessPolicy, class SerializePolicy>
class member_tinfo<T, AccessPolicy, SerializePolicy, true, false>
: public detail::abstract_uniform_type_info<T> {
public:
using value_type = typename std::underlying_type<T>::type;
public:
member_tinfo(AccessPolicy apol, SerializePolicy spol)
: m_apol(std::move(apol)), m_spol(std::move(spol)) {}
member_tinfo(AccessPolicy apol) : m_apol(std::move(apol)) {}
member_tinfo() {}
member_tinfo() = default;
void serialize(const void* p, serializer* s) const override {
auto val = m_apol(p);
......@@ -319,18 +335,17 @@ class member_tinfo<T, AccessPolicy, SerializePolicy, true, false>
private:
AccessPolicy m_apol;
SerializePolicy m_spol;
};
template <class T, class C>
class memptr_access_policy {
public:
inline memptr_access_policy(T C::*memptr) : m_memptr(memptr) {
// nop
}
memptr_access_policy(const memptr_access_policy&) = default;
memptr_access_policy& operator=(const memptr_access_policy&) = default;
inline memptr_access_policy(T C::*memptr) : m_memptr(memptr) {}
inline T& operator()(void* vptr) const {
auto ptr = reinterpret_cast<C*>(vptr);
return *ptr.*m_memptr;
......@@ -355,7 +370,6 @@ class memptr_access_policy {
template <class C, typename GRes, typename SRes, typename SArg>
class getter_setter_access_policy {
public:
using getter = GRes (C::*)() const;
......@@ -377,15 +391,12 @@ class getter_setter_access_policy {
static constexpr bool grants_mutable_access = false;
private:
getter m_get;
setter m_set;
};
template <class T>
struct fake_access_policy {
inline T& operator()(void* vptr) const {
return *reinterpret_cast<T*>(vptr);
}
......@@ -400,7 +411,6 @@ struct fake_access_policy {
}
static constexpr bool grants_mutable_access = true;
};
template <class T, class C>
......@@ -436,15 +446,13 @@ uniform_type_info_ptr new_member_tinfo(GRes (C::*getter)() const,
using value_type = typename detail::rm_const_and_ref<GRes>::type;
using tinfo = member_tinfo<value_type, access_policy,
forwarding_serialize_policy>;
return uniform_type_info_ptr(
new tinfo(access_policy(getter, setter), std::move(meminf)));
return uniform_type_info_ptr(new tinfo(access_policy(getter, setter),
std::move(meminf)));
}
template <class T>
class default_uniform_type_info : public detail::abstract_uniform_type_info<T> {
public:
template <class... Ts>
default_uniform_type_info(Ts&&... args) {
push_back(std::forward<Ts>(args)...);
......@@ -457,22 +465,24 @@ class default_uniform_type_info : public detail::abstract_uniform_type_info<T> {
void serialize(const void* obj, serializer* s) const override {
// serialize each member
for (auto& m : m_members) m->serialize(obj, s);
for (auto& m : m_members) {
m->serialize(obj, s);
}
}
void deserialize(void* obj, deserializer* d) const override {
// deserialize each member
for (auto& m : m_members) m->deserialize(obj, d);
for (auto& m : m_members) {
m->deserialize(obj, d);
}
}
protected:
bool pod_mems_equals(const T& lhs, const T& rhs) const override {
return pod_eq(lhs, rhs);
}
private:
template <class C>
typename std::enable_if<std::is_pod<C>::value, bool>::type
pod_eq(const C& lhs, const C& rhs) const {
......@@ -488,8 +498,9 @@ class default_uniform_type_info : public detail::abstract_uniform_type_info<T> {
return false;
}
// terminates recursion
inline void push_back() {}
inline void push_back() {
// terminate recursion
}
template <class R, class C, class... Ts>
void push_back(R C::*memptr, Ts&&... args) {
......@@ -535,18 +546,17 @@ class default_uniform_type_info : public detail::abstract_uniform_type_info<T> {
}
std::vector<uniform_type_info_ptr> m_members;
};
template <class... Rs>
class default_uniform_type_info<typed_actor<
Rs...>> : public detail::abstract_uniform_type_info<typed_actor<Rs...>> {
class default_uniform_type_info<typed_actor<Rs...>> :
public detail::abstract_uniform_type_info<typed_actor<Rs...>> {
public:
using handle_type = typed_actor<Rs...>;
default_uniform_type_info() { sub_uti = uniform_typeid<actor>(); }
default_uniform_type_info() {
sub_uti = uniform_typeid<actor>();
}
void serialize(const void* obj, serializer* s) const override {
auto tmp = actor_cast<actor>(deref(obj).address());
......@@ -560,17 +570,13 @@ class default_uniform_type_info<typed_actor<
}
private:
const uniform_type_info* sub_uti;
static handle_type& deref(void* ptr) {
return *reinterpret_cast<handle_type*>(ptr);
}
static const handle_type& deref(const void* ptr) {
return *reinterpret_cast<const handle_type*>(ptr);
}
const uniform_type_info* sub_uti;
};
} // namespace detail
......
......@@ -479,6 +479,16 @@ struct type_at<0, T0, Ts...> {
using type = T0;
};
template <class T>
struct is_optional : std::false_type {
// no members
};
template <class T>
struct is_optional<optional<T>> : std::true_type {
// no members
};
} // namespace detail
} // namespace caf
......
......@@ -335,19 +335,13 @@ struct to_guard<anything, false> {
template <class T>
struct to_guard<detail::wrapped<T>, false> : to_guard<anything> {};
template <class T>
struct is_optional : std::false_type {};
template <class T>
struct is_optional<optional<T>> : std::true_type {};
template <class T>
struct to_guard<T, true> {
using ct = typename detail::get_callable_trait<T>::type;
using arg_types = typename ct::arg_types;
static_assert(detail::tl_size<arg_types>::value == 1,
"projection/guard must take exactly one argument");
static_assert(is_optional<typename ct::result_type>::value,
static_assert(detail::is_optional<typename ct::result_type>::value,
"projection/guard must return an optional value");
using value_type =
typename std::conditional<
......@@ -355,8 +349,9 @@ struct to_guard<T, true> {
T*,
T
>::type;
static value_type _(value_type val) { return val; }
static value_type _(value_type val) {
return val;
}
};
template <class T>
......
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