1#ifndef BOOST_MP11_SET_HPP_INCLUDED
2#define BOOST_MP11_SET_HPP_INCLUDED
3
4// Copyright 2015, 2019 Peter Dimov.
5//
6// Distributed under the Boost Software License, Version 1.0.
7//
8// See accompanying file LICENSE_1_0.txt or copy at
9// http://www.boost.org/LICENSE_1_0.txt
10
11#include <boost/mp11/utility.hpp>
12#include <boost/mp11/function.hpp>
13#include <boost/mp11/detail/mp_list.hpp>
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>
18#include <type_traits>
19
20namespace boost
21{
22namespace mp11
23{
24
25// mp_set_contains<S, V>
26namespace detail
27{
28
29template<class S, class V> struct mp_set_contains_impl
30{
31};
32
33template<template<class...> class L, class... T, class V> struct mp_set_contains_impl<L<T...>, V>
34{
35 using type = mp_to_bool<std::is_base_of<mp_identity<V>, mp_inherit<mp_identity<T>...> > >;
36};
37
38} // namespace detail
39
40template<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...>
43namespace detail
44{
45
46template<class S, class... T> struct mp_set_push_back_impl
47{
48};
49
50template<template<class...> class L, class... U> struct mp_set_push_back_impl<L<U...>>
51{
52 using type = L<U...>;
53};
54
55template<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
63template<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...>
66namespace detail
67{
68
69template<class S, class... T> struct mp_set_push_front_impl
70{
71};
72
73template<template<class...> class L, class... U> struct mp_set_push_front_impl<L<U...>>
74{
75 using type = L<U...>;
76};
77
78template<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
83template<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
91template<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>
94namespace detail
95{
96
97template<class S> struct mp_is_set_impl
98{
99 using type = mp_false;
100};
101
102template<template<class...> class L, class... T> struct mp_is_set_impl<L<T...>>
103{
104 using type = mp_to_bool<std::is_same<mp_list<T...>, mp_set_push_back<mp_list<>, T...> > >;
105};
106
107} // namespace detail
108
109template<class S> using mp_is_set = typename detail::mp_is_set_impl<S>::type;
110
111// mp_set_union<L...>
112namespace detail
113{
114
115template<class... L> struct mp_set_union_impl
116{
117};
118
119template<> struct mp_set_union_impl<>
120{
121 using type = mp_list<>;
122};
123
124template<template<class...> class L, class... T> struct mp_set_union_impl<L<T...>>
125{
126 using type = L<T...>;
127};
128
129template<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
134template<class L1, class... L> using mp_set_union_ = typename mp_set_union_impl<L1, mp_append<mp_list<>, L...>>::type;
135
136template<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
142template<class... L> using mp_set_union = typename detail::mp_set_union_impl<L...>::type;
143
144// mp_set_intersection<S...>
145namespace detail
146{
147
148template<class... S> struct in_all_sets
149{
150 template<class T> using fn = mp_all< mp_set_contains<S, T>... >;
151};
152
153template<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
155template<class... S> struct mp_set_intersection_impl
156{
157};
158
159template<> struct mp_set_intersection_impl<>
160{
161 using type = mp_list<>;
162};
163
164template<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
170template<class... S> using mp_set_intersection = typename detail::mp_set_intersection_impl<S...>::type;
171
172// mp_set_difference<L, S...>
173namespace detail
174{
175
176template<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
183template<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
185} // namespace mp11
186} // namespace boost
187
188#endif // #ifndef BOOST_MP11_SET_HPP_INCLUDED
189

source code of include/boost/mp11/set.hpp