]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | #ifndef BOOST_MP11_SET_HPP_INCLUDED |
2 | #define BOOST_MP11_SET_HPP_INCLUDED | |
3 | ||
92f5a8d4 | 4 | // Copyright 2015, 2019 Peter Dimov. |
b32b8144 | 5 | // |
92f5a8d4 | 6 | // Distributed under the Boost Software License, Version 1.0. |
b32b8144 | 7 | // |
92f5a8d4 TL |
8 | // See accompanying file LICENSE_1_0.txt or copy at |
9 | // http://www.boost.org/LICENSE_1_0.txt | |
b32b8144 FG |
10 | |
11 | #include <boost/mp11/utility.hpp> | |
92f5a8d4 | 12 | #include <boost/mp11/function.hpp> |
b32b8144 | 13 | #include <boost/mp11/detail/mp_list.hpp> |
92f5a8d4 TL |
14 | #include <boost/mp11/detail/mp_append.hpp> |
15 | #include <boost/mp11/detail/mp_copy_if.hpp> | |
16 | #include <boost/mp11/detail/mp_remove_if.hpp> | |
17 | #include <boost/mp11/detail/mp_is_list.hpp> | |
b32b8144 FG |
18 | #include <type_traits> |
19 | ||
20 | namespace boost | |
21 | { | |
22 | namespace mp11 | |
23 | { | |
24 | ||
25 | // mp_set_contains<S, V> | |
26 | namespace detail | |
27 | { | |
28 | ||
92f5a8d4 TL |
29 | template<class S, class V> struct mp_set_contains_impl |
30 | { | |
31 | }; | |
b32b8144 FG |
32 | |
33 | template<template<class...> class L, class... T, class V> struct mp_set_contains_impl<L<T...>, V> | |
34 | { | |
92f5a8d4 | 35 | using type = mp_to_bool<std::is_base_of<mp_identity<V>, mp_inherit<mp_identity<T>...> > >; |
b32b8144 FG |
36 | }; |
37 | ||
38 | } // namespace detail | |
39 | ||
40 | template<class S, class V> using mp_set_contains = typename detail::mp_set_contains_impl<S, V>::type; | |
41 | ||
42 | // mp_set_push_back<S, T...> | |
43 | namespace detail | |
44 | { | |
45 | ||
92f5a8d4 TL |
46 | template<class S, class... T> struct mp_set_push_back_impl |
47 | { | |
48 | }; | |
b32b8144 FG |
49 | |
50 | template<template<class...> class L, class... U> struct mp_set_push_back_impl<L<U...>> | |
51 | { | |
52 | using type = L<U...>; | |
53 | }; | |
54 | ||
55 | template<template<class...> class L, class... U, class T1, class... T> struct mp_set_push_back_impl<L<U...>, T1, T...> | |
56 | { | |
57 | using S = mp_if<mp_set_contains<L<U...>, T1>, L<U...>, L<U..., T1>>; | |
58 | using type = typename mp_set_push_back_impl<S, T...>::type; | |
59 | }; | |
60 | ||
61 | } // namespace detail | |
62 | ||
63 | template<class S, class... T> using mp_set_push_back = typename detail::mp_set_push_back_impl<S, T...>::type; | |
64 | ||
65 | // mp_set_push_front<S, T...> | |
66 | namespace detail | |
67 | { | |
68 | ||
92f5a8d4 TL |
69 | template<class S, class... T> struct mp_set_push_front_impl |
70 | { | |
71 | }; | |
b32b8144 FG |
72 | |
73 | template<template<class...> class L, class... U> struct mp_set_push_front_impl<L<U...>> | |
74 | { | |
75 | using type = L<U...>; | |
76 | }; | |
77 | ||
78 | template<template<class...> class L, class... U, class T1> struct mp_set_push_front_impl<L<U...>, T1> | |
79 | { | |
80 | using type = mp_if<mp_set_contains<L<U...>, T1>, L<U...>, L<T1, U...>>; | |
81 | }; | |
82 | ||
83 | template<template<class...> class L, class... U, class T1, class... T> struct mp_set_push_front_impl<L<U...>, T1, T...> | |
84 | { | |
85 | using S = typename mp_set_push_front_impl<L<U...>, T...>::type; | |
86 | using type = typename mp_set_push_front_impl<S, T1>::type; | |
87 | }; | |
88 | ||
89 | } // namespace detail | |
90 | ||
91 | template<class S, class... T> using mp_set_push_front = typename detail::mp_set_push_front_impl<S, T...>::type; | |
92 | ||
93 | // mp_is_set<S> | |
94 | namespace detail | |
95 | { | |
96 | ||
97 | template<class S> struct mp_is_set_impl | |
98 | { | |
99 | using type = mp_false; | |
100 | }; | |
101 | ||
102 | template<template<class...> class L, class... T> struct mp_is_set_impl<L<T...>> | |
103 | { | |
92f5a8d4 | 104 | using type = mp_to_bool<std::is_same<mp_list<T...>, mp_set_push_back<mp_list<>, T...> > >; |
b32b8144 FG |
105 | }; |
106 | ||
107 | } // namespace detail | |
108 | ||
109 | template<class S> using mp_is_set = typename detail::mp_is_set_impl<S>::type; | |
110 | ||
92f5a8d4 TL |
111 | // mp_set_union<L...> |
112 | namespace detail | |
113 | { | |
114 | ||
115 | template<class... L> struct mp_set_union_impl | |
116 | { | |
117 | }; | |
118 | ||
119 | template<> struct mp_set_union_impl<> | |
120 | { | |
121 | using type = mp_list<>; | |
122 | }; | |
123 | ||
124 | template<template<class...> class L, class... T> struct mp_set_union_impl<L<T...>> | |
125 | { | |
126 | using type = L<T...>; | |
127 | }; | |
128 | ||
129 | template<template<class...> class L1, class... T1, template<class...> class L2, class... T2> struct mp_set_union_impl<L1<T1...>, L2<T2...>> | |
130 | { | |
131 | using type = mp_set_push_back<L1<T1...>, T2...>; | |
132 | }; | |
133 | ||
134 | template<class L1, class... L> using mp_set_union_ = typename mp_set_union_impl<L1, mp_append<mp_list<>, L...>>::type; | |
135 | ||
136 | template<class L1, class L2, class L3, class... L> struct mp_set_union_impl<L1, L2, L3, L...>: mp_defer<mp_set_union_, L1, L2, L3, L...> | |
137 | { | |
138 | }; | |
139 | ||
140 | } // namespace detail | |
141 | ||
142 | template<class... L> using mp_set_union = typename detail::mp_set_union_impl<L...>::type; | |
143 | ||
144 | // mp_set_intersection<S...> | |
145 | namespace detail | |
146 | { | |
147 | ||
148 | template<class... S> struct in_all_sets | |
149 | { | |
150 | template<class T> using fn = mp_all< mp_set_contains<S, T>... >; | |
151 | }; | |
152 | ||
153 | template<class L, class... S> using mp_set_intersection_ = mp_if< mp_all<mp_is_list<S>...>, mp_copy_if_q<L, detail::in_all_sets<S...>> >; | |
154 | ||
155 | template<class... S> struct mp_set_intersection_impl | |
156 | { | |
157 | }; | |
158 | ||
159 | template<> struct mp_set_intersection_impl<> | |
160 | { | |
161 | using type = mp_list<>; | |
162 | }; | |
163 | ||
164 | template<class L, class... S> struct mp_set_intersection_impl<L, S...>: mp_defer<mp_set_intersection_, L, S...> | |
165 | { | |
166 | }; | |
167 | ||
168 | } // namespace detail | |
169 | ||
170 | template<class... S> using mp_set_intersection = typename detail::mp_set_intersection_impl<S...>::type; | |
171 | ||
172 | // mp_set_difference<L, S...> | |
173 | namespace detail | |
174 | { | |
175 | ||
176 | template<class... S> struct in_any_set | |
177 | { | |
178 | template<class T> using fn = mp_any< mp_set_contains<S, T>... >; | |
179 | }; | |
180 | ||
181 | } // namespace detail | |
182 | ||
183 | template<class L, class... S> using mp_set_difference = mp_if< mp_all<mp_is_list<S>...>, mp_remove_if_q<L, detail::in_any_set<S...>> >; | |
184 | ||
b32b8144 FG |
185 | } // namespace mp11 |
186 | } // namespace boost | |
187 | ||
188 | #endif // #ifndef BOOST_MP11_SET_HPP_INCLUDED |