Commit db73ab96 authored by Dominik Charousset's avatar Dominik Charousset

Fix build on MSVC

parent c1c603c1
...@@ -30,16 +30,13 @@ ...@@ -30,16 +30,13 @@
#include "caf/unifyn.hpp" #include "caf/unifyn.hpp"
#define CAF_READ_INSPECTOR_TRY(statement) \ #define CAF_READ_INSPECTOR_TRY(statement) \
using CAF_UNIFYN(statement_result) = decltype(statement); \ if constexpr (std::is_same<decltype(statement), void>::value) { \
if constexpr (std::is_same<CAF_UNIFYN(statement_result), void>::value) { \
statement; \ statement; \
} else if constexpr (std::is_same<CAF_UNIFYN(statement_result), \ } else { \
bool>::value) { \ if (auto err = statement) { \
if (!statement) \ result = err; \
return false; \ return false; \
} else if (auto err = statement) { \ } \
result = err; \
return false; \
} }
namespace caf { namespace caf {
...@@ -54,59 +51,8 @@ public: ...@@ -54,59 +51,8 @@ public:
template <class... Ts> template <class... Ts>
[[nodiscard]] auto operator()(Ts&&... xs) { [[nodiscard]] auto operator()(Ts&&... xs) {
auto& dref = *static_cast<Subtype*>(this);
typename Subtype::result_type result; typename Subtype::result_type result;
auto f = [&result, &dref](auto&& x) { static_cast<void>((try_apply(result, xs) && ...));
using type = std::remove_const_t<std::remove_reference_t<decltype(x)>>;
if constexpr (std::is_empty<type>::value) {
// nop
} else if constexpr (meta::is_save_callback_v<type>) {
CAF_READ_INSPECTOR_TRY(x.fun())
} else if constexpr (meta::is_annotation_v<type> //
|| is_allowed_unsafe_message_type_v<type>) {
// skip element
} else if constexpr (detail::can_apply_v<Subtype, decltype(x)>) {
using apply_type = decltype(dref.apply(x));
if constexpr (std::is_same<apply_type, void>::value) {
dref.apply(x);
} else if constexpr (std::is_same<apply_type, bool>::value) {
if (!dref.apply(x)) {
result = sec::end_of_stream;
return false;
}
} else {
CAF_READ_INSPECTOR_TRY(dref.apply(x))
}
} else if constexpr (std::is_integral<type>::value) {
using squashed_type = detail::squashed_int_t<type>;
CAF_READ_INSPECTOR_TRY(dref.apply(static_cast<squashed_type>(x)))
} else if constexpr (std::is_array<type>::value) {
CAF_READ_INSPECTOR_TRY(apply_array(dref, x))
} else if constexpr (detail::is_stl_tuple_type<type>::value) {
std::make_index_sequence<std::tuple_size<type>::value> seq;
CAF_READ_INSPECTOR_TRY(apply_tuple(dref, x, seq))
} else if constexpr (detail::is_map_like<type>::value) {
CAF_READ_INSPECTOR_TRY(dref.begin_sequence(x.size()))
for (const auto& kvp : x) {
CAF_READ_INSPECTOR_TRY(dref(kvp.first, kvp.second))
}
CAF_READ_INSPECTOR_TRY(dref.end_sequence())
} else if constexpr (detail::is_list_like<type>::value) {
CAF_READ_INSPECTOR_TRY(dref.begin_sequence(x.size()))
for (const auto& value : x) {
CAF_READ_INSPECTOR_TRY(dref(value))
}
CAF_READ_INSPECTOR_TRY(dref.end_sequence())
} else {
static_assert(detail::is_inspectable<Subtype, type>::value);
using caf::detail::inspect;
// We require that the implementation for `inspect` does not modify its
// arguments when passing a reading inspector.
CAF_READ_INSPECTOR_TRY(inspect(dref, const_cast<type&>(x)));
}
return true;
};
static_cast<void>((f(std::forward<Ts>(xs)) && ...));
return result; return result;
} }
...@@ -118,14 +64,58 @@ private: ...@@ -118,14 +64,58 @@ private:
} }
template <class T, size_t... Is> template <class T, size_t... Is>
static auto apply_array(Subtype& dref, T* xs, std::index_sequence<Is...>) { static auto
apply_array(Subtype& dref, const T* xs, std::index_sequence<Is...>) {
return dref(xs[Is]...); return dref(xs[Is]...);
} }
template <class T, size_t N> template <class R, class T>
static auto apply_array(Subtype& dref, T (&xs)[N]) { std::enable_if_t<meta::is_annotation_v<T>, bool> try_apply(R& result, T& x) {
std::make_index_sequence<N> seq; if constexpr (meta::is_save_callback_v<T>)
return apply_array(dref, xs, seq); CAF_READ_INSPECTOR_TRY(x.fun())
return true;
}
template <class R, class T>
std::enable_if_t<!meta::is_annotation_v<T>, bool>
try_apply(R& result, const T& x) {
Subtype& dref = *static_cast<Subtype*>(this);
if constexpr (std::is_empty<T>::value
|| is_allowed_unsafe_message_type_v<T>) {
// skip element
} else if constexpr (detail::can_apply_v<Subtype, decltype(x)>) {
CAF_READ_INSPECTOR_TRY(dref.apply(x))
} else if constexpr (std::is_integral<T>::value) {
using squashed_type = detail::squashed_int_t<T>;
auto squashed_x = static_cast<squashed_type>(x);
CAF_READ_INSPECTOR_TRY(dref.apply(squashed_x))
} else if constexpr (std::is_array<T>::value) {
std::make_index_sequence<std::extent<T>::value> seq;
CAF_READ_INSPECTOR_TRY(apply_array(dref, x, seq))
} else if constexpr (detail::is_stl_tuple_type<T>::value) {
std::make_index_sequence<std::tuple_size<T>::value> seq;
CAF_READ_INSPECTOR_TRY(apply_tuple(dref, x, seq))
} else if constexpr (detail::is_map_like<T>::value) {
CAF_READ_INSPECTOR_TRY(dref.begin_sequence(x.size()))
for (const auto& kvp : x) {
CAF_READ_INSPECTOR_TRY(dref(kvp.first, kvp.second))
}
CAF_READ_INSPECTOR_TRY(dref.end_sequence())
} else if constexpr (detail::is_list_like<T>::value) {
CAF_READ_INSPECTOR_TRY(dref.begin_sequence(x.size()))
for (const auto& value : x) {
CAF_READ_INSPECTOR_TRY(dref(value))
}
CAF_READ_INSPECTOR_TRY(dref.end_sequence())
} else {
static_assert(detail::is_inspectable<Subtype, T>::value);
using caf::detail::inspect;
// We require that the implementation for `inspect` does not modify its
// arguments when passing a reading inspector.
auto& mutable_x = const_cast<T&>(x);
CAF_READ_INSPECTOR_TRY(inspect(dref, mutable_x));
}
return true;
} }
}; };
......
...@@ -34,9 +34,11 @@ ...@@ -34,9 +34,11 @@
#define CAF_WRITE_INSPECTOR_TRY(statement) \ #define CAF_WRITE_INSPECTOR_TRY(statement) \
if constexpr (std::is_same<decltype(statement), void>::value) { \ if constexpr (std::is_same<decltype(statement), void>::value) { \
statement; \ statement; \
} else if (auto err = statement) { \ } else { \
result = err; \ if (auto err = statement) { \
return false; \ result = err; \
return false; \
} \
} }
namespace caf { namespace caf {
...@@ -56,58 +58,11 @@ public: ...@@ -56,58 +58,11 @@ public:
template <class... Ts> template <class... Ts>
[[nodiscard]] auto operator()(Ts&&... xs) { [[nodiscard]] auto operator()(Ts&&... xs) {
auto& dref = *static_cast<Subtype*>(this); static_assert(
((std::is_lvalue_reference<Ts>::value || meta::is_annotation_v<Ts>) //
&&...));
typename Subtype::result_type result; typename Subtype::result_type result;
auto f = [&result, &dref](auto&& x) { static_cast<void>((try_apply(result, xs) && ...));
using type = std::remove_reference_t<decltype(x)>;
if constexpr (std::is_empty<type>::value) {
// nop
} else if constexpr (meta::is_load_callback_v<type>) {
CAF_WRITE_INSPECTOR_TRY(x.fun())
} else if constexpr (meta::is_annotation_v<type> //
|| is_allowed_unsafe_message_type_v<type>) {
// skip element
} else if constexpr (detail::can_apply_v<Subtype, decltype(x)>) {
CAF_WRITE_INSPECTOR_TRY(dref.apply(x))
} else if constexpr (std::is_integral<type>::value) {
using squashed_type = detail::squashed_int_t<type>;
CAF_WRITE_INSPECTOR_TRY(dref.apply(reinterpret_cast<squashed_type&>(x)))
} else if constexpr (std::is_array<type>::value) {
CAF_WRITE_INSPECTOR_TRY(apply_array(dref, x))
} else if constexpr (detail::is_stl_tuple_type_v<type>) {
std::make_index_sequence<std::tuple_size<type>::value> seq;
CAF_WRITE_INSPECTOR_TRY(apply_tuple(dref, x, seq))
} else if constexpr (detail::is_map_like_v<type>) {
x.clear();
size_t size = 0;
CAF_WRITE_INSPECTOR_TRY(dref.begin_sequence(size))
for (size_t i = 0; i < size; ++i) {
auto key = typename type::key_type{};
auto val = typename type::mapped_type{};
CAF_WRITE_INSPECTOR_TRY(dref(key, val))
x.emplace(std::move(key), std::move(val));
}
CAF_WRITE_INSPECTOR_TRY(dref.end_sequence())
} else if constexpr (detail::is_list_like_v<type>) {
x.clear();
size_t size = 0;
CAF_WRITE_INSPECTOR_TRY(dref.begin_sequence(size))
for (size_t i = 0; i < size; ++i) {
auto tmp = typename type::value_type{};
CAF_WRITE_INSPECTOR_TRY(dref(tmp))
x.insert(x.end(), std::move(tmp));
}
CAF_WRITE_INSPECTOR_TRY(dref.end_sequence())
} else {
static_assert(std::is_lvalue_reference<decltype(x)>::value //
&& !std::is_const<decltype(x)>::value);
static_assert(detail::is_inspectable<Subtype, type>::value);
using caf::detail::inspect;
CAF_WRITE_INSPECTOR_TRY(inspect(dref, x));
}
return true;
};
static_cast<void>((f(std::forward<Ts>(xs)) && ...));
return result; return result;
} }
...@@ -123,10 +78,58 @@ private: ...@@ -123,10 +78,58 @@ private:
return dref(xs[Is]...); return dref(xs[Is]...);
} }
template <class T, size_t N> template <class R, class T>
static auto apply_array(Subtype& dref, T (&xs)[N]) { std::enable_if_t<meta::is_annotation_v<T>, bool> try_apply(R& result, T& x) {
std::make_index_sequence<N> seq; if constexpr (meta::is_load_callback_v<T>)
return apply_array(dref, xs, seq); CAF_WRITE_INSPECTOR_TRY(x.fun())
return true;
}
template <class R, class T>
std::enable_if_t<!meta::is_annotation_v<T>, bool> try_apply(R& result, T& x) {
Subtype& dref = *static_cast<Subtype*>(this);
if constexpr (std::is_empty<T>::value
|| is_allowed_unsafe_message_type_v<T>) {
// skip element
} else if constexpr (detail::can_apply_v<Subtype, decltype(x)>) {
CAF_WRITE_INSPECTOR_TRY(dref.apply(x))
} else if constexpr (std::is_integral<T>::value) {
using squashed_type = detail::squashed_int_t<T>;
auto& squashed_x = reinterpret_cast<squashed_type&>(x);
CAF_WRITE_INSPECTOR_TRY(dref.apply(squashed_x))
} else if constexpr (std::is_array<T>::value) {
std::make_index_sequence<std::extent<T>::value> seq;
CAF_WRITE_INSPECTOR_TRY(apply_array(dref, x, seq))
} else if constexpr (detail::is_stl_tuple_type_v<T>) {
std::make_index_sequence<std::tuple_size<T>::value> seq;
CAF_WRITE_INSPECTOR_TRY(apply_tuple(dref, x, seq))
} else if constexpr (detail::is_map_like_v<T>) {
x.clear();
size_t size = 0;
CAF_WRITE_INSPECTOR_TRY(dref.begin_sequence(size))
for (size_t i = 0; i < size; ++i) {
auto key = typename T::key_type{};
auto val = typename T::mapped_type{};
CAF_WRITE_INSPECTOR_TRY(dref(key, val))
x.emplace(std::move(key), std::move(val));
}
CAF_WRITE_INSPECTOR_TRY(dref.end_sequence())
} else if constexpr (detail::is_list_like_v<T>) {
x.clear();
size_t size = 0;
CAF_WRITE_INSPECTOR_TRY(dref.begin_sequence(size))
for (size_t i = 0; i < size; ++i) {
auto tmp = typename T::value_type{};
CAF_WRITE_INSPECTOR_TRY(dref(tmp))
x.insert(x.end(), std::move(tmp));
}
CAF_WRITE_INSPECTOR_TRY(dref.end_sequence())
} else {
static_assert(detail::is_inspectable<Subtype, T>::value);
using caf::detail::inspect;
CAF_WRITE_INSPECTOR_TRY(inspect(dref, x));
}
return true;
} }
}; };
......
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