Skip to content

Commit

Permalink
Fix types traversal
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-sparus committed Jun 7, 2024
1 parent fe6f91a commit e59027d
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 27 deletions.
56 changes: 35 additions & 21 deletions immer/extra/persist/common/type_traverse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ namespace detail {

namespace hana = boost::hana;

template <class T, class = void>
struct get_inner_types_t
template <class T>
struct single_type_t
{
static auto apply()
{
Expand All @@ -27,6 +27,10 @@ struct get_inner_types_t
}
};

template <class T, class = void>
struct get_inner_types_t : single_type_t<T>
{};

template <class T>
struct get_inner_types_t<T, std::enable_if_t<hana::Struct<T>::value>>
{
Expand All @@ -45,19 +49,19 @@ template <typename T,
immer::detail::rbts::bits_t B,
immer::detail::rbts::bits_t BL>
struct get_inner_types_t<immer::vector<T, MemoryPolicy, B, BL>>
: get_inner_types_t<T>
: single_type_t<T>
{};

template <typename T,
typename MemoryPolicy,
immer::detail::rbts::bits_t B,
immer::detail::rbts::bits_t BL>
struct get_inner_types_t<immer::flex_vector<T, MemoryPolicy, B, BL>>
: get_inner_types_t<T>
: single_type_t<T>
{};

template <typename T, typename MemoryPolicy>
struct get_inner_types_t<immer::box<T, MemoryPolicy>> : get_inner_types_t<T>
struct get_inner_types_t<immer::box<T, MemoryPolicy>> : single_type_t<T>
{};

template <typename T,
Expand All @@ -66,7 +70,7 @@ template <typename T,
typename MemoryPolicy,
immer::detail::hamts::bits_t B>
struct get_inner_types_t<immer::set<T, Hash, Equal, MemoryPolicy, B>>
: get_inner_types_t<T>
: single_type_t<T>
{};

template <typename K,
Expand All @@ -79,8 +83,8 @@ struct get_inner_types_t<immer::map<K, T, Hash, Equal, MemoryPolicy, B>>
{
static auto apply()
{
return hana::concat(get_inner_types_t<K>::apply(),
get_inner_types_t<T>::apply());
return hana::concat(single_type_t<K>::apply(),
single_type_t<T>::apply());
}
};

Expand All @@ -91,7 +95,7 @@ template <typename T,
typename MemoryPolicy,
immer::detail::hamts::bits_t B>
struct get_inner_types_t<immer::table<T, KeyFn, Hash, Equal, MemoryPolicy, B>>
: get_inner_types_t<T>
: single_type_t<T>
{};

template <class... Types>
Expand Down Expand Up @@ -122,13 +126,7 @@ constexpr auto insert_conditionally = [](auto map, auto pair) {
}
};

} // namespace detail

/**
* Generate a map (type, member_name) for all members of a given type,
* recursively.
*/
inline auto get_inner_types_map(const auto& type)
inline auto get_inner_types_map_with_empty_strings(const auto& type)
{
namespace hana = boost::hana;

Expand All @@ -152,19 +150,35 @@ inline auto get_inner_types_map(const auto& type)

auto expanded = hana::while_(
can_expand, hana::to_map(get_for_one_type(type)), get_for_many);
return expanded;
}

} // namespace detail

/**
* Generate a map (type, member_name) for all members of a given type,
* recursively.
*/
inline auto get_inner_types_map(const auto& type)
{
namespace hana = boost::hana;

auto with_empty_strings =
detail::get_inner_types_map_with_empty_strings(type);

// Throw away types we don't know names for
const auto empty_string = BOOST_HANA_STRING("");
auto result =
hana::filter(hana::to_tuple(expanded), [empty_string](auto pair) {
return hana::second(pair) != empty_string;
});
auto result = hana::filter(hana::to_tuple(with_empty_strings),
[empty_string](auto pair) {
return hana::second(pair) != empty_string;
});
return hana::to_map(result);
}

inline auto get_inner_types(const auto& type)
{
return boost::hana::keys(get_inner_types_map(type));
return boost::hana::keys(
detail::get_inner_types_map_with_empty_strings(type));
}

} // namespace immer::persist::util
5 changes: 4 additions & 1 deletion immer/extra/persist/json/wrap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

#include <immer/extra/persist/common/type_traverse.hpp>
#include <immer/extra/persist/json/persistable.hpp>
#include <immer/extra/persist/rbts/pool.hpp>

#include <immer/extra/persist/box/pool.hpp>
#include <immer/extra/persist/champ/traits.hpp>
#include <immer/extra/persist/rbts/traits.hpp>

namespace immer::persist {

Expand Down
36 changes: 31 additions & 5 deletions test/extra/persist/test_special_pool_auto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -932,15 +932,41 @@ struct foos
struct with_variant
{
BOOST_HANA_DEFINE_STRUCT(with_variant,
(std::variant<double, foos>, something));
(std::variant<double, foos>, something),
(immer::map<int, immer::vector<std::string>>,
int_map)

);
};
} // namespace test_variant

TEST_CASE("It goes inside variant")
TEST_CASE("Test types traversal")
{
auto names = immer::persist::get_named_pools_for_type(
hana::type_c<test_variant::with_variant>);
using contains_t = decltype(names[hana::type_c<immer::vector<int>>] ==
BOOST_HANA_STRING("ints"));
static_assert(contains_t::value);
SECTION("It goes inside variant")
{
using contains_t = decltype(names[hana::type_c<immer::vector<int>>] ==
BOOST_HANA_STRING("ints"));
static_assert(contains_t::value);
}

SECTION("Check types with names")
{
using contains_map_t =
decltype(names[hana::type_c<
immer::map<int, immer::vector<std::string>>>] ==
BOOST_HANA_STRING("int_map"));
static_assert(contains_map_t::value);

// It doesn't find the vector because there is no name for it
const auto vector_type = hana::type_c<immer::vector<std::string>>;
static_assert(decltype(hana::contains(names, vector_type) ==
hana::false_c)::value);

// But it has the vector when we don't use names
auto only_types = immer::persist::get_pools_for_type(
hana::type_c<test_variant::with_variant>);
static_assert(decltype(hana::contains(only_types, vector_type))::value);
}
}

0 comments on commit e59027d

Please sign in to comment.