3 Defines `boost::hana::set`.
5 @copyright Louis Dionne 2013-2017
6 Distributed under the Boost Software License, Version 1.0.
7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
10 #ifndef BOOST_HANA_SET_HPP
11 #define BOOST_HANA_SET_HPP
13 #include <boost/hana/fwd/set.hpp>
15 #include <boost/hana/at.hpp>
16 #include <boost/hana/bool.hpp>
17 #include <boost/hana/concept/comparable.hpp>
18 #include <boost/hana/concept/constant.hpp>
19 #include <boost/hana/concept/hashable.hpp>
20 #include <boost/hana/config.hpp>
21 #include <boost/hana/contains.hpp>
22 #include <boost/hana/core/make.hpp>
23 #include <boost/hana/core/to.hpp>
24 #include <boost/hana/detail/decay.hpp>
25 #include <boost/hana/detail/fast_and.hpp>
26 #include <boost/hana/detail/has_duplicates.hpp>
27 #include <boost/hana/detail/operators/adl.hpp>
28 #include <boost/hana/detail/operators/comparable.hpp>
29 #include <boost/hana/detail/operators/searchable.hpp>
30 #include <boost/hana/equal.hpp>
31 #include <boost/hana/erase_key.hpp>
32 #include <boost/hana/find_if.hpp>
33 #include <boost/hana/fold_left.hpp>
34 #include <boost/hana/fwd/any_of.hpp>
35 #include <boost/hana/fwd/core/to.hpp>
36 #include <boost/hana/fwd/difference.hpp>
37 #include <boost/hana/fwd/intersection.hpp>
38 #include <boost/hana/fwd/union.hpp>
39 #include <boost/hana/insert.hpp>
40 #include <boost/hana/is_subset.hpp>
41 #include <boost/hana/length.hpp>
42 #include <boost/hana/or.hpp>
43 #include <boost/hana/remove.hpp>
44 #include <boost/hana/tuple.hpp>
45 #include <boost/hana/unpack.hpp>
46 #include <boost/hana/value.hpp>
49 #include <type_traits>
53 BOOST_HANA_NAMESPACE_BEGIN
54 //////////////////////////////////////////////////////////////////////////
56 //////////////////////////////////////////////////////////////////////////
58 template <typename ...Xs>
60 : detail::operators::adl<set<Xs...>>
61 , detail::searchable_operators<set<Xs...>>
64 using hana_tag = set_tag;
65 static constexpr std::size_t size = sizeof...(Xs);
67 explicit constexpr set(tuple<Xs...> const& xs)
71 explicit constexpr set(tuple<Xs...>&& xs)
72 : storage(static_cast<tuple<Xs...>&&>(xs))
75 constexpr set() = default;
76 constexpr set(set const& other) = default;
77 constexpr set(set&& other) = default;
81 //////////////////////////////////////////////////////////////////////////
83 //////////////////////////////////////////////////////////////////////////
86 struct comparable_operators<set_tag> {
87 static constexpr bool value = true;
91 //////////////////////////////////////////////////////////////////////////
93 //////////////////////////////////////////////////////////////////////////
95 struct make_impl<set_tag> {
96 template <typename ...Xs>
97 static constexpr auto apply(Xs&& ...xs) {
98 #if defined(BOOST_HANA_CONFIG_ENABLE_DEBUG_MODE)
99 static_assert(detail::fast_and<hana::Comparable<Xs>::value...>::value,
100 "hana::make_set(xs...) requires all the 'xs' to be Comparable");
102 static_assert(detail::fast_and<hana::Hashable<Xs>::value...>::value,
103 "hana::make_set(xs...) requires all the 'xs' to be Hashable");
105 static_assert(detail::fast_and<
106 Constant<decltype(hana::equal(xs, xs))>::value...
108 "hana::make_set(xs...) requires all the 'xs' to be "
109 "Comparable at compile-time");
111 static_assert(!detail::has_duplicates<Xs&&...>::value,
112 "hana::make_set(xs...) requires all the 'xs' to be unique");
115 return set<typename detail::decay<Xs>::type...>{
116 hana::make_tuple(static_cast<Xs&&>(xs)...)
121 //////////////////////////////////////////////////////////////////////////
123 //////////////////////////////////////////////////////////////////////////
125 struct equal_impl<set_tag, set_tag> {
126 template <typename S1, typename S2>
127 static constexpr auto equal_helper(S1 const& s1, S2 const& s2, hana::true_)
128 { return hana::is_subset(s1, s2); }
130 template <typename S1, typename S2>
131 static constexpr auto equal_helper(S1 const&, S2 const&, hana::false_)
132 { return hana::false_c; }
134 template <typename S1, typename S2>
135 static constexpr decltype(auto) apply(S1&& s1, S2&& s2) {
136 return equal_impl::equal_helper(s1, s2, hana::bool_c<
137 decltype(hana::length(s1.storage))::value ==
138 decltype(hana::length(s2.storage))::value
143 //////////////////////////////////////////////////////////////////////////
145 //////////////////////////////////////////////////////////////////////////
147 struct unpack_impl<set_tag> {
148 template <typename Set, typename F>
149 static constexpr decltype(auto) apply(Set&& set, F&& f) {
150 return hana::unpack(static_cast<Set&&>(set).storage,
151 static_cast<F&&>(f));
155 //////////////////////////////////////////////////////////////////////////
157 //////////////////////////////////////////////////////////////////////////
159 struct find_if_impl<set_tag> {
160 template <typename Xs, typename Pred>
161 static constexpr auto apply(Xs&& xs, Pred&& pred) {
162 return hana::find_if(static_cast<Xs&&>(xs).storage, static_cast<Pred&&>(pred));
167 struct any_of_impl<set_tag> {
168 template <typename Pred>
169 struct any_of_helper {
171 template <typename ...X>
172 constexpr auto operator()(X const& ...x) const {
173 return hana::or_(pred(x)...);
175 constexpr auto operator()() const {
176 return hana::false_c;
180 template <typename Xs, typename Pred>
181 static constexpr auto apply(Xs const& xs, Pred const& pred) {
182 return hana::unpack(xs.storage, any_of_helper<Pred>{pred});
187 struct is_subset_impl<set_tag, set_tag> {
188 template <typename Ys>
189 struct all_contained {
191 template <typename ...X>
192 constexpr auto operator()(X const& ...x) const {
193 return hana::bool_c<detail::fast_and<
194 hana::value<decltype(hana::contains(ys, x))>()...
199 template <typename Xs, typename Ys>
200 static constexpr auto apply(Xs const& xs, Ys const& ys) {
201 return hana::unpack(xs, all_contained<Ys>{ys});
205 //////////////////////////////////////////////////////////////////////////
207 //////////////////////////////////////////////////////////////////////////
208 template <typename F>
209 struct to_impl<set_tag, F, when<hana::Foldable<F>::value>> {
210 template <typename Xs>
211 static constexpr decltype(auto) apply(Xs&& xs) {
212 return hana::fold_left(static_cast<Xs&&>(xs),
218 //////////////////////////////////////////////////////////////////////////
220 //////////////////////////////////////////////////////////////////////////
222 struct insert_impl<set_tag> {
223 template <typename Xs, typename X, typename Indices>
224 static constexpr auto
225 insert_helper(Xs&& xs, X&&, hana::true_, Indices) {
226 return static_cast<Xs&&>(xs);
229 template <typename Xs, typename X, std::size_t ...n>
230 static constexpr auto
231 insert_helper(Xs&& xs, X&& x, hana::false_, std::index_sequence<n...>) {
232 return hana::make_set(
233 hana::at_c<n>(static_cast<Xs&&>(xs).storage)..., static_cast<X&&>(x)
237 template <typename Xs, typename X>
238 static constexpr auto apply(Xs&& xs, X&& x) {
239 constexpr bool c = hana::value<decltype(hana::contains(xs, x))>();
240 constexpr std::size_t size = std::remove_reference<Xs>::type::size;
241 return insert_helper(static_cast<Xs&&>(xs), static_cast<X&&>(x),
242 hana::bool_c<c>, std::make_index_sequence<size>{});
246 //////////////////////////////////////////////////////////////////////////
248 //////////////////////////////////////////////////////////////////////////
250 struct erase_key_impl<set_tag> {
251 template <typename Xs, typename X>
252 static constexpr decltype(auto) apply(Xs&& xs, X&& x) {
254 hana::remove(static_cast<Xs&&>(xs).storage,
255 static_cast<X&&>(x)),
261 //////////////////////////////////////////////////////////////////////////
263 //////////////////////////////////////////////////////////////////////////
265 template <typename Ys>
266 struct set_insert_if_contains {
269 template <typename Result, typename Key>
270 static constexpr auto helper(Result&& result, Key&& key, hana::true_) {
271 return hana::insert(static_cast<Result&&>(result), static_cast<Key&&>(key));
274 template <typename Result, typename Key>
275 static constexpr auto helper(Result&& result, Key&&, hana::false_) {
276 return static_cast<Result&&>(result);
279 template <typename Result, typename Key>
280 constexpr auto operator()(Result&& result, Key&& key) const {
281 constexpr bool keep = hana::value<decltype(hana::contains(ys, key))>();
282 return set_insert_if_contains::helper(static_cast<Result&&>(result),
283 static_cast<Key&&>(key),
290 struct intersection_impl<set_tag> {
291 template <typename Xs, typename Ys>
292 static constexpr auto apply(Xs&& xs, Ys const& ys) {
293 return hana::fold_left(static_cast<Xs&&>(xs), hana::make_set(),
294 detail::set_insert_if_contains<Ys>{ys});
298 //////////////////////////////////////////////////////////////////////////
300 //////////////////////////////////////////////////////////////////////////
302 struct union_impl<set_tag> {
303 template <typename Xs, typename Ys>
304 static constexpr auto apply(Xs&& xs, Ys&& ys) {
305 return hana::fold_left(static_cast<Xs&&>(xs), static_cast<Ys&&>(ys),
310 //////////////////////////////////////////////////////////////////////////
312 //////////////////////////////////////////////////////////////////////////
314 struct difference_impl<set_tag> {
315 template <typename Xs, typename Ys>
316 static constexpr auto apply(Xs&& xs, Ys&& ys) {
317 return hana::fold_left(static_cast<Ys&&>(ys), static_cast<Xs&&>(xs),
321 BOOST_HANA_NAMESPACE_END
323 #endif // !BOOST_HANA_SET_HPP