| 1 | /*! |
| 2 | @file |
| 3 | Forward declares `boost::hana::set`. |
| 4 | |
| 5 | Copyright Louis Dionne 2013-2022 |
| 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) |
| 8 | */ |
| 9 | |
| 10 | #ifndef BOOST_HANA_FWD_SET_HPP |
| 11 | #define BOOST_HANA_FWD_SET_HPP |
| 12 | |
| 13 | #include <boost/hana/config.hpp> |
| 14 | #include <boost/hana/fwd/core/to.hpp> |
| 15 | #include <boost/hana/fwd/core/make.hpp> |
| 16 | #include <boost/hana/fwd/erase_key.hpp> |
| 17 | |
| 18 | |
| 19 | namespace boost { namespace hana { |
| 20 | //! @ingroup group-datatypes |
| 21 | //! Basic unordered container requiring unique, `Comparable` and |
| 22 | //! `Hashable` keys. |
| 23 | //! |
| 24 | //! A set is an unordered container that can hold heterogeneous keys. |
| 25 | //! A set requires (and ensures) that no duplicates are present when |
| 26 | //! inserting new keys. |
| 27 | //! |
| 28 | //! @note |
| 29 | //! The actual representation of a `hana::set` is implementation-defined. |
| 30 | //! In particular, one should not take for granted the order of the |
| 31 | //! template parameters and the presence of any additional constructors |
| 32 | //! or assignment operators than what is documented. The canonical way of |
| 33 | //! creating a `hana::set` is through `hana::make_set`. More details |
| 34 | //! [in the tutorial](@ref tutorial-containers-types). |
| 35 | //! |
| 36 | //! |
| 37 | //! Modeled concepts |
| 38 | //! ---------------- |
| 39 | //! 1. `Comparable`\n |
| 40 | //! Two sets are equal iff they contain the same elements, regardless of |
| 41 | //! the order. |
| 42 | //! @include example/set/comparable.cpp |
| 43 | //! |
| 44 | //! 2. Foldable\n |
| 45 | //! Folding a set is equivalent to folding the sequence of its values. |
| 46 | //! However, note that the values are not required to be in any specific |
| 47 | //! order, so using the folds provided here with an operation that is not |
| 48 | //! both commutative and associative will yield non-deterministic behavior. |
| 49 | //! @include example/set/foldable.cpp |
| 50 | //! |
| 51 | //! 3. Searchable\n |
| 52 | //! The elements in a set act as both its keys and its values. Since the |
| 53 | //! elements of a set are unique, searching for an element will return |
| 54 | //! either the only element which is equal to the searched value, or |
| 55 | //! `nothing`. Also note that `operator[]` can be used instead of the |
| 56 | //! `at_key` function. |
| 57 | //! @include example/set/searchable.cpp |
| 58 | //! |
| 59 | //! |
| 60 | //! Conversion from any `Foldable` |
| 61 | //! ------------------------------ |
| 62 | //! Any `Foldable` structure can be converted into a `hana::set` with |
| 63 | //! `to<set_tag>`. The elements of the structure must all be compile-time |
| 64 | //! `Comparable`. If the structure contains duplicate elements, only |
| 65 | //! the first occurence will appear in the resulting set. More |
| 66 | //! specifically, conversion from a `Foldable` is equivalent to |
| 67 | //! @code |
| 68 | //! to<set_tag>(xs) == fold_left(xs, make_set(), insert) |
| 69 | //! @endcode |
| 70 | //! |
| 71 | //! __Example__ |
| 72 | //! @include example/set/to.cpp |
| 73 | #ifdef BOOST_HANA_DOXYGEN_INVOKED |
| 74 | template <typename implementation_defined> |
| 75 | struct set { |
| 76 | //! Default-construct a set. This constructor only exists when all the |
| 77 | //! elements of the set are default-constructible. |
| 78 | constexpr set() = default; |
| 79 | |
| 80 | //! Copy-construct a set from another set. This constructor only |
| 81 | //! exists when all the elements of the set are copy-constructible. |
| 82 | constexpr set(set const& other) = default; |
| 83 | |
| 84 | //! Move-construct a set from another set. This constructor only |
| 85 | //! exists when all the elements of the set are move-constructible. |
| 86 | constexpr set(set&& other) = default; |
| 87 | |
| 88 | //! Equivalent to `hana::equal` |
| 89 | template <typename X, typename Y> |
| 90 | friend constexpr auto operator==(X&& x, Y&& y); |
| 91 | |
| 92 | //! Equivalent to `hana::not_equal` |
| 93 | template <typename X, typename Y> |
| 94 | friend constexpr auto operator!=(X&& x, Y&& y); |
| 95 | |
| 96 | //! Equivalent to `hana::at_key` |
| 97 | template <typename Key> |
| 98 | constexpr decltype(auto) operator[](Key&& key); |
| 99 | }; |
| 100 | #else |
| 101 | template <typename ...Xs> |
| 102 | struct set; |
| 103 | #endif |
| 104 | |
| 105 | //! Tag representing the `hana::set` container. |
| 106 | //! @relates hana::set |
| 107 | struct set_tag { }; |
| 108 | |
| 109 | //! Function object for creating a `hana::set`. |
| 110 | //! @relates hana::set |
| 111 | //! |
| 112 | //! Given zero or more values `xs...`, `make<set_tag>` returns a `set` |
| 113 | //! containing those values. The values must all be compile-time |
| 114 | //! `Comparable`, and no duplicate values may be provided. To create |
| 115 | //! a `set` from a sequence with possible duplicates, use `to<set_tag>` |
| 116 | //! instead. |
| 117 | //! |
| 118 | //! |
| 119 | //! Example |
| 120 | //! ------- |
| 121 | //! @include example/set/make.cpp |
| 122 | #ifdef BOOST_HANA_DOXYGEN_INVOKED |
| 123 | template <> |
| 124 | constexpr auto make<set_tag> = [](auto&& ...xs) { |
| 125 | return set<implementation_defined>{forwarded(xs)...}; |
| 126 | }; |
| 127 | #endif |
| 128 | |
| 129 | //! Equivalent to `make<set_tag>`; provided for convenience. |
| 130 | //! @relates hana::set |
| 131 | //! |
| 132 | //! |
| 133 | //! Example |
| 134 | //! ------- |
| 135 | //! @include example/set/make.cpp |
| 136 | BOOST_HANA_INLINE_VARIABLE constexpr auto make_set = make<set_tag>; |
| 137 | |
| 138 | //! Insert an element in a `hana::set`. |
| 139 | //! @relates hana::set |
| 140 | //! |
| 141 | //! If the set already contains an element that compares equal, then |
| 142 | //! nothing is done and the set is returned as is. |
| 143 | //! |
| 144 | //! |
| 145 | //! @param set |
| 146 | //! The set in which to insert a value. |
| 147 | //! |
| 148 | //! @param element |
| 149 | //! The value to insert. It must be compile-time `Comparable`. |
| 150 | //! |
| 151 | //! |
| 152 | //! Example |
| 153 | //! ------- |
| 154 | //! @include example/set/insert.cpp |
| 155 | #ifdef BOOST_HANA_DOXYGEN_INVOKED |
| 156 | constexpr auto insert = [](auto&& set, auto&& element) { |
| 157 | return tag-dispatched; |
| 158 | }; |
| 159 | #endif |
| 160 | |
| 161 | //! Remove an element from a `hana::set`. |
| 162 | //! @relates hana::set |
| 163 | //! |
| 164 | //! Returns a new set containing all the elements of the original, |
| 165 | //! except the one comparing `equal` to the given element. If the set |
| 166 | //! does not contain such an element, a new set equal to the original |
| 167 | //! set is returned. |
| 168 | //! |
| 169 | //! |
| 170 | //! @param set |
| 171 | //! The set in which to remove a value. |
| 172 | //! |
| 173 | //! @param element |
| 174 | //! The value to remove. It must be compile-time `Comparable`. |
| 175 | //! |
| 176 | //! |
| 177 | //! Example |
| 178 | //! ------- |
| 179 | //! @include example/set/erase_key.cpp |
| 180 | #ifdef BOOST_HANA_DOXYGEN_INVOKED |
| 181 | constexpr auto erase_key = [](auto&& set, auto&& element) { |
| 182 | return tag-dispatched; |
| 183 | }; |
| 184 | #endif |
| 185 | |
| 186 | //! Returns the union of two sets. |
| 187 | //! @relates hana::set |
| 188 | //! |
| 189 | //! Given two sets `xs` and `ys`, `union_(xs, ys)` is a new set containing |
| 190 | //! all the elements of `xs` and all the elements of `ys`, without |
| 191 | //! duplicates. For any object `x`, the following holds: `x` is in |
| 192 | //! `hana::union_(xs, ys)` if and only if `x` is in `xs` or `x` is in `ys`. |
| 193 | //! |
| 194 | //! |
| 195 | //! @param xs, ys |
| 196 | //! Two sets to compute the union of. |
| 197 | //! |
| 198 | //! |
| 199 | //! Example |
| 200 | //! ------- |
| 201 | //! @include example/set/union.cpp |
| 202 | #ifdef BOOST_HANA_DOXYGEN_INVOKED |
| 203 | constexpr auto union_ = [](auto&& xs, auto&& ys) { |
| 204 | return tag-dispatched; |
| 205 | }; |
| 206 | #endif |
| 207 | |
| 208 | //! Returns the intersection of two sets. |
| 209 | //! @relates hana::set |
| 210 | //! |
| 211 | //! Given two sets `xs` and `ys`, `intersection(xs, ys)` is a new set |
| 212 | //! containing exactly those elements that are present both in `xs` and |
| 213 | //! in `ys`. |
| 214 | //! In other words, the following holds for any object `x`: |
| 215 | //! @code |
| 216 | //! x ^in^ intersection(xs, ys) if and only if x ^in^ xs && x ^in^ ys |
| 217 | //! @endcode |
| 218 | //! |
| 219 | //! |
| 220 | //! @param xs, ys |
| 221 | //! Two sets to intersect. |
| 222 | //! |
| 223 | //! |
| 224 | //! Example |
| 225 | //! ------- |
| 226 | //! @include example/set/intersection.cpp |
| 227 | #ifdef BOOST_HANA_DOXYGEN_INVOKED |
| 228 | constexpr auto intersection = [](auto&& xs, auto&& ys) { |
| 229 | return tag-dispatched; |
| 230 | }; |
| 231 | #endif |
| 232 | //! Equivalent to `to<set_tag>`; provided for convenience. |
| 233 | //! @relates hana::set |
| 234 | constexpr auto to_set = to<set_tag>; |
| 235 | |
| 236 | //! Returns the set-theoretic difference of two sets. |
| 237 | //! @relates hana::set |
| 238 | //! |
| 239 | //! Given two sets `xs` and `ys`, `difference(xs, ys)` is a new set |
| 240 | //! containing all the elements of `xs` that are _not_ contained in `ys`. |
| 241 | //! For any object `x`, the following holds: |
| 242 | //! @code |
| 243 | //! x ^in^ difference(xs, ys) if and only if x ^in^ xs && !(x ^in^ ys) |
| 244 | //! @endcode |
| 245 | //! |
| 246 | //! |
| 247 | //! This operation is not commutative, i.e. `difference(xs, ys)` is not |
| 248 | //! necessarily the same as `difference(ys, xs)`. Indeed, consider the |
| 249 | //! case where `xs` is empty and `ys` isn't. Then, `difference(xs, ys)` |
| 250 | //! is empty but `difference(ys, xs)` is equal to `ys`. For the symmetric |
| 251 | //! version of this operation, see `symmetric_difference`. |
| 252 | //! |
| 253 | //! |
| 254 | //! @param xs |
| 255 | //! A set param to remove values from. |
| 256 | //! |
| 257 | //! @param ys |
| 258 | //! The set whose values are removed from `xs`. |
| 259 | //! |
| 260 | //! |
| 261 | //! Example |
| 262 | //! ------- |
| 263 | //! @include example/set/difference.cpp |
| 264 | #ifdef BOOST_HANA_DOXYGEN_INVOKED |
| 265 | constexpr auto difference = [](auto&& xs, auto&& ys) { |
| 266 | return tag-dispatched; |
| 267 | }; |
| 268 | #endif |
| 269 | |
| 270 | //! Returns the symmetric set-theoretic difference of two sets. |
| 271 | //! @relates hana::set |
| 272 | //! |
| 273 | //! Given two sets `xs` and `ys`, `symmetric_difference(xs, ys)` is a new |
| 274 | //! set containing all the elements of `xs` that are not contained in `ys`, |
| 275 | //! and all the elements of `ys` that are not contained in `xs`. The |
| 276 | //! symmetric difference of two sets satisfies the following: |
| 277 | //! @code |
| 278 | //! symmetric_difference(xs, ys) == union_(difference(xs, ys), difference(ys, xs)) |
| 279 | //! @endcode |
| 280 | //! |
| 281 | //! |
| 282 | //! @param xs, ys |
| 283 | //! Two sets to compute the symmetric difference of. |
| 284 | //! |
| 285 | //! |
| 286 | //! Example |
| 287 | //! ------- |
| 288 | //! @include example/set/symmetric_difference.cpp |
| 289 | #ifdef BOOST_HANA_DOXYGEN_INVOKED |
| 290 | constexpr auto symmetric_difference = [](auto&& xs, auto&& ys) { |
| 291 | return tag-dispatched; |
| 292 | }; |
| 293 | #endif |
| 294 | |
| 295 | |
| 296 | }} // end namespace boost::hana |
| 297 | |
| 298 | #endif // !BOOST_HANA_FWD_SET_HPP |
| 299 | |