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