/*! @file Defines `boost::hana::set`. @copyright Louis Dionne 2013-2017 Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) */ #ifndef BOOST_HANA_SET_HPP #define BOOST_HANA_SET_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include BOOST_HANA_NAMESPACE_BEGIN ////////////////////////////////////////////////////////////////////////// // set ////////////////////////////////////////////////////////////////////////// //! @cond template struct set final : detail::operators::adl> , detail::searchable_operators> { tuple storage; using hana_tag = set_tag; static constexpr std::size_t size = sizeof...(Xs); explicit constexpr set(tuple const& xs) : storage(xs) { } explicit constexpr set(tuple&& xs) : storage(static_cast&&>(xs)) { } constexpr set() = default; constexpr set(set const& other) = default; constexpr set(set&& other) = default; }; //! @endcond ////////////////////////////////////////////////////////////////////////// // Operators ////////////////////////////////////////////////////////////////////////// namespace detail { template <> struct comparable_operators { static constexpr bool value = true; }; } ////////////////////////////////////////////////////////////////////////// // make ////////////////////////////////////////////////////////////////////////// template <> struct make_impl { template static constexpr auto apply(Xs&& ...xs) { #if defined(BOOST_HANA_CONFIG_ENABLE_DEBUG_MODE) static_assert(detail::fast_and::value...>::value, "hana::make_set(xs...) requires all the 'xs' to be Comparable"); static_assert(detail::fast_and::value...>::value, "hana::make_set(xs...) requires all the 'xs' to be Hashable"); static_assert(detail::fast_and< Constant::value... >::value, "hana::make_set(xs...) requires all the 'xs' to be " "Comparable at compile-time"); static_assert(!detail::has_duplicates::value, "hana::make_set(xs...) requires all the 'xs' to be unique"); #endif return set::type...>{ hana::make_tuple(static_cast(xs)...) }; } }; ////////////////////////////////////////////////////////////////////////// // Comparable ////////////////////////////////////////////////////////////////////////// template <> struct equal_impl { template static constexpr auto equal_helper(S1 const& s1, S2 const& s2, hana::true_) { return hana::is_subset(s1, s2); } template static constexpr auto equal_helper(S1 const&, S2 const&, hana::false_) { return hana::false_c; } template static constexpr decltype(auto) apply(S1&& s1, S2&& s2) { return equal_impl::equal_helper(s1, s2, hana::bool_c< decltype(hana::length(s1.storage))::value == decltype(hana::length(s2.storage))::value >); } }; ////////////////////////////////////////////////////////////////////////// // Foldable ////////////////////////////////////////////////////////////////////////// template <> struct unpack_impl { template static constexpr decltype(auto) apply(Set&& set, F&& f) { return hana::unpack(static_cast(set).storage, static_cast(f)); } }; ////////////////////////////////////////////////////////////////////////// // Searchable ////////////////////////////////////////////////////////////////////////// template <> struct find_if_impl { template static constexpr auto apply(Xs&& xs, Pred&& pred) { return hana::find_if(static_cast(xs).storage, static_cast(pred)); } }; template <> struct any_of_impl { template struct any_of_helper { Pred const& pred; template constexpr auto operator()(X const& ...x) const { return hana::or_(pred(x)...); } constexpr auto operator()() const { return hana::false_c; } }; template static constexpr auto apply(Xs const& xs, Pred const& pred) { return hana::unpack(xs.storage, any_of_helper{pred}); } }; template <> struct is_subset_impl { template struct all_contained { Ys const& ys; template constexpr auto operator()(X const& ...x) const { return hana::bool_c()... >::value>; } }; template static constexpr auto apply(Xs const& xs, Ys const& ys) { return hana::unpack(xs, all_contained{ys}); } }; ////////////////////////////////////////////////////////////////////////// // Conversions ////////////////////////////////////////////////////////////////////////// template struct to_impl::value>> { template static constexpr decltype(auto) apply(Xs&& xs) { return hana::fold_left(static_cast(xs), hana::make_set(), hana::insert); } }; ////////////////////////////////////////////////////////////////////////// // insert ////////////////////////////////////////////////////////////////////////// template <> struct insert_impl { template static constexpr auto insert_helper(Xs&& xs, X&&, hana::true_, Indices) { return static_cast(xs); } template static constexpr auto insert_helper(Xs&& xs, X&& x, hana::false_, std::index_sequence) { return hana::make_set( hana::at_c(static_cast(xs).storage)..., static_cast(x) ); } template static constexpr auto apply(Xs&& xs, X&& x) { constexpr bool c = hana::value(); constexpr std::size_t size = std::remove_reference::type::size; return insert_helper(static_cast(xs), static_cast(x), hana::bool_c, std::make_index_sequence{}); } }; ////////////////////////////////////////////////////////////////////////// // erase_key ////////////////////////////////////////////////////////////////////////// template <> struct erase_key_impl { template static constexpr decltype(auto) apply(Xs&& xs, X&& x) { return hana::unpack( hana::remove(static_cast(xs).storage, static_cast(x)), hana::make_set ); } }; ////////////////////////////////////////////////////////////////////////// // intersection ////////////////////////////////////////////////////////////////////////// namespace detail { template struct set_insert_if_contains { Ys const& ys; template static constexpr auto helper(Result&& result, Key&& key, hana::true_) { return hana::insert(static_cast(result), static_cast(key)); } template static constexpr auto helper(Result&& result, Key&&, hana::false_) { return static_cast(result); } template constexpr auto operator()(Result&& result, Key&& key) const { constexpr bool keep = hana::value(); return set_insert_if_contains::helper(static_cast(result), static_cast(key), hana::bool_c); } }; } template <> struct intersection_impl { template static constexpr auto apply(Xs&& xs, Ys const& ys) { return hana::fold_left(static_cast(xs), hana::make_set(), detail::set_insert_if_contains{ys}); } }; ////////////////////////////////////////////////////////////////////////// // union_ ////////////////////////////////////////////////////////////////////////// template <> struct union_impl { template static constexpr auto apply(Xs&& xs, Ys&& ys) { return hana::fold_left(static_cast(xs), static_cast(ys), hana::insert); } }; ////////////////////////////////////////////////////////////////////////// // difference ////////////////////////////////////////////////////////////////////////// template <> struct difference_impl { template static constexpr auto apply(Xs&& xs, Ys&& ys) { return hana::fold_left(static_cast(ys), static_cast(xs), hana::erase_key); } }; BOOST_HANA_NAMESPACE_END #endif // !BOOST_HANA_SET_HPP