Commit 3939ed96 authored by Dominik Charousset's avatar Dominik Charousset

Fix dispatching in the default inspector

parent a33284be
...@@ -25,6 +25,8 @@ is based on [Keep a Changelog](https://keepachangelog.com). ...@@ -25,6 +25,8 @@ is based on [Keep a Changelog](https://keepachangelog.com).
configuration files and CLI arguments (#1145). configuration files and CLI arguments (#1145).
- Restore correct functionality of `middleman::remote_lookup` (#1146). This - Restore correct functionality of `middleman::remote_lookup` (#1146). This
fixes a regression introduced in version 0.18.0-rc.1 fixes a regression introduced in version 0.18.0-rc.1
- Fixed an endless recursion when using the `default_inspector` from `inspect`
overloads (#1147).
## [0.18.0-rc.1] - 2020-09-09 ## [0.18.0-rc.1] - 2020-09-09
......
...@@ -459,13 +459,7 @@ struct default_inspector_access : inspector_access_base<T> { ...@@ -459,13 +459,7 @@ struct default_inspector_access : inspector_access_base<T> {
template <class Inspector> template <class Inspector>
[[nodiscard]] static bool apply_object(Inspector& f, T& x) { [[nodiscard]] static bool apply_object(Inspector& f, T& x) {
// Dispatch to user-provided `inspect` overload or assume a trivial type. // Dispatch to user-provided `inspect` overload or assume a trivial type.
if constexpr (detail::has_inspect_overload<Inspector, T>::value) { if constexpr (std::is_empty<T>::value) {
using result_type = decltype(inspect(f, x));
if constexpr (std::is_same<result_type, bool>::value)
return inspect(f, x);
else
return apply_deprecated(f, x);
} else if constexpr (std::is_empty<T>::value) {
return f.object(x).fields(); return f.object(x).fields();
} else { } else {
return f.object(x).fields(f.field("value", x)); return f.object(x).fields(f.field("value", x));
...@@ -475,7 +469,7 @@ struct default_inspector_access : inspector_access_base<T> { ...@@ -475,7 +469,7 @@ struct default_inspector_access : inspector_access_base<T> {
/// Applies `x` as a single value to `f`. /// Applies `x` as a single value to `f`.
template <class Inspector> template <class Inspector>
[[nodiscard]] static bool apply_value(Inspector& f, T& x) { [[nodiscard]] static bool apply_value(Inspector& f, T& x) {
constexpr auto token = inspect_value_access_type<Inspector, T>(); constexpr auto token = nested_inspect_value_access_type<Inspector, T>();
if constexpr (Inspector::is_loading) if constexpr (Inspector::is_loading)
return detail::load_value(f, x, token); return detail::load_value(f, x, token);
else else
...@@ -881,8 +875,6 @@ struct inspector_access<std::chrono::duration<Rep, Period>> ...@@ -881,8 +875,6 @@ struct inspector_access<std::chrono::duration<Rep, Period>>
: inspector_access_base<std::chrono::duration<Rep, Period>> { : inspector_access_base<std::chrono::duration<Rep, Period>> {
using value_type = std::chrono::duration<Rep, Period>; using value_type = std::chrono::duration<Rep, Period>;
using default_impl = default_inspector_access<value_type>;
template <class Inspector> template <class Inspector>
static bool apply_object(Inspector& f, value_type& x) { static bool apply_object(Inspector& f, value_type& x) {
return f.object(x).fields(f.field("value", x)); return f.object(x).fields(f.field("value", x));
...@@ -919,8 +911,6 @@ struct inspector_access< ...@@ -919,8 +911,6 @@ struct inspector_access<
using value_type using value_type
= std::chrono::time_point<std::chrono::system_clock, Duration>; = std::chrono::time_point<std::chrono::system_clock, Duration>;
using default_impl = default_inspector_access<value_type>;
template <class Inspector> template <class Inspector>
static bool apply_object(Inspector& f, value_type& x) { static bool apply_object(Inspector& f, value_type& x) {
return f.object(x).fields(f.field("value", x)); return f.object(x).fields(f.field("value", x));
......
...@@ -150,4 +150,38 @@ constexpr auto inspect_value_access_type() { ...@@ -150,4 +150,38 @@ constexpr auto inspect_value_access_type() {
return inspector_access_type::none{}; return inspector_access_type::none{};
} }
/// Same as `inspect_value_access_type`, but ignores specialization of
/// `inspector_access` as well as `inspect` and `inspect_value` overloads.
/// @relates inspector_access_type
template <class Inspector, class T>
constexpr auto nested_inspect_value_access_type() {
// Order: unsafe (error) > C Array > builtin_inspect > inspector_access >
// inspect_value > inspect > defaults.
// This is the same as in inspect_object_access_type, except that we pick up
// inspect_value overloads.
using namespace detail;
if constexpr (is_allowed_unsafe_message_type_v<T>)
return inspector_access_type::unsafe{};
else if constexpr (std::is_array<T>::value)
return inspector_access_type::array{};
else if constexpr (has_builtin_inspect<Inspector, T>::value)
return inspector_access_type::builtin{};
else if constexpr (is_trivial_inspector_value_v<Inspector::is_loading, T>)
return inspector_access_type::trivial{};
else if constexpr (std::is_integral<T>::value)
return inspector_access_type::integral{};
else if constexpr (std::is_enum<T>::value)
return inspector_access_type::enumeration{};
else if constexpr (std::is_empty<T>::value)
return inspector_access_type::empty{};
else if constexpr (is_stl_tuple_type_v<T>)
return inspector_access_type::tuple{};
else if constexpr (is_map_like_v<T>)
return inspector_access_type::map{};
else if constexpr (is_list_like_v<T>)
return inspector_access_type::list{};
else
return inspector_access_type::none{};
}
} // namespace caf } // namespace caf
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "caf/binary_serializer.hpp" #include "caf/binary_serializer.hpp"
#include "core-test.hpp" #include "core-test.hpp"
#include "nasty.hpp"
#include <cstring> #include <cstring>
#include <vector> #include <vector>
...@@ -206,6 +207,10 @@ CAF_TEST(binary serializer picks up inspect functions) { ...@@ -206,6 +207,10 @@ CAF_TEST(binary serializer picks up inspect functions) {
'u'_b, 'm'_b, ' '_b, 'd'_b, 'o'_b, 'l'_b, 'o'_b, 'r'_b, ' '_b, 'u'_b, 'm'_b, ' '_b, 'd'_b, 'o'_b, 'l'_b, 'o'_b, 'r'_b, ' '_b,
's'_b, 'i'_b, 't'_b, ' '_b, 'a'_b, 'm'_b, 'e'_b, 't'_b, '.'_b); 's'_b, 'i'_b, 't'_b, ' '_b, 'a'_b, 'm'_b, 'e'_b, 't'_b, '.'_b);
} }
SUBTEST("enum class with non-default overload") {
auto day = weekday::friday;
CHECK_LOAD(weekday, day, 0x04_b);
}
} }
CAF_TEST_FIXTURE_SCOPE_END() CAF_TEST_FIXTURE_SCOPE_END()
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "caf/binary_serializer.hpp" #include "caf/binary_serializer.hpp"
#include "core-test.hpp" #include "core-test.hpp"
#include "nasty.hpp"
#include <cstring> #include <cstring>
#include <vector> #include <vector>
...@@ -204,6 +205,10 @@ CAF_TEST(binary serializer picks up inspect functions) { ...@@ -204,6 +205,10 @@ CAF_TEST(binary serializer picks up inspect functions) {
'u'_b, 'm'_b, ' '_b, 'd'_b, 'o'_b, 'l'_b, 'o'_b, 'r'_b, ' '_b, 'u'_b, 'm'_b, ' '_b, 'd'_b, 'o'_b, 'l'_b, 'o'_b, 'r'_b, ' '_b,
's'_b, 'i'_b, 't'_b, ' '_b, 'a'_b, 'm'_b, 'e'_b, 't'_b, '.'_b); 's'_b, 'i'_b, 't'_b, ' '_b, 'a'_b, 'm'_b, 'e'_b, 't'_b, '.'_b);
} }
SUBTEST("enum class with non-default overload") {
auto day = weekday::friday;
CHECK_SAVE(weekday, day, 0x04_b);
}
} }
CAF_TEST_FIXTURE_SCOPE_END() CAF_TEST_FIXTURE_SCOPE_END()
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "caf/string_view.hpp" #include "caf/string_view.hpp"
#include "caf/variant.hpp" #include "caf/variant.hpp"
enum class weekday { enum class weekday : uint8_t {
monday, monday,
tuesday, tuesday,
wednesday, wednesday,
......
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