| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | //====================================================================================================================== | ||
| 2 | /* | ||
| 3 | KUMI - Compact Tuple Tools | ||
| 4 | Copyright : KUMI Project Contributors | ||
| 5 | SPDX-License-Identifier: BSL-1.0 | ||
| 6 | */ | ||
| 7 | //====================================================================================================================== | ||
| 8 | #pragma once | ||
| 9 | |||
| 10 | namespace kumi | ||
| 11 | { | ||
| 12 | namespace _ | ||
| 13 | { | ||
| 14 | template<typename T, typename... Ts> | ||
| 15 | inline constexpr bool contains = ((kumi::concepts::field<T> && std::invocable<T, kumi::_::tag_of_t<Ts>>) || ...); | ||
| 16 | |||
| 17 | template<typename T, typename ID, std::size_t... I> | ||
| 18 | 28 | KUMI_HIDDEN_ABI constexpr auto contains_(kumi::_::adl_tag_t, T&&, ID const&, std::index_sequence<I...>) | |
| 19 | { | ||
| 20 | return std::bool_constant< | ||
| 21 | 28 | kumi::concepts::contains_identifier<std::remove_cvref_t<ID>, kumi::element_t<I, T>...>>{}; | |
| 22 | } | ||
| 23 | |||
| 24 | template<typename T, std::size_t... I, typename... Is> | ||
| 25 | 12 | KUMI_HIDDEN_ABI constexpr auto contains_only_(kumi::_::adl_tag_t, T&&, std::index_sequence<I...>, Is const&...) | |
| 26 | { | ||
| 27 | 12 | return std::bool_constant<(kumi::_::contains<kumi::element_t<I, T>, Is...> && ...)>{}; | |
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | struct contains_t | ||
| 32 | { | ||
| 33 | template<kumi::concepts::product_type T, kumi::concepts::identifier ID> | ||
| 34 | [[nodiscard]] KUMI_ABI constexpr auto operator()(T&& t, ID const& id) const noexcept | ||
| 35 | { | ||
| 36 | if constexpr (kumi::concepts::empty_product_type<T>) return std::false_type{}; | ||
| 37 | 14 | else return contains_(kumi::_::adl_tag, KUMI_FWD(t), id, kumi::function::indexes_for<T>{}); | |
| 38 | } | ||
| 39 | }; | ||
| 40 | |||
| 41 | struct contains_any_t | ||
| 42 | { | ||
| 43 | template<kumi::concepts::product_type T, kumi::concepts::identifier... Is> | ||
| 44 | [[nodiscard]] KUMI_ABI constexpr auto operator()([[maybe_unused]] T&& t, Is const&... ids) const noexcept | ||
| 45 | { | ||
| 46 | if constexpr (kumi::concepts::empty_product_type<T>) return std::false_type{}; | ||
| 47 | else if constexpr (sizeof...(Is) == 0) return std::false_type{}; | ||
| 48 | else | ||
| 49 | return std::bool_constant<( | ||
| 50 | 4 | decltype(contains_(kumi::_::adl_tag, std::declval<T>(), ids, kumi::function::indexes_for<T>{})){} || ...)>{}; | |
| 51 | } | ||
| 52 | }; | ||
| 53 | |||
| 54 | struct contains_only_t | ||
| 55 | { | ||
| 56 | template<kumi::concepts::product_type T, kumi::concepts::identifier... Is> | ||
| 57 | [[nodiscard]] KUMI_ABI constexpr auto operator()([[maybe_unused]] T&& t, | ||
| 58 | [[maybe_unused]] Is const&... ids) const noexcept | ||
| 59 | { | ||
| 60 | if constexpr (kumi::concepts::empty_product_type<T>) return std::false_type{}; | ||
| 61 | else if constexpr (sizeof...(Is) == 0) return std::false_type{}; | ||
| 62 | 8 | else if constexpr (sizeof...(Is) < kumi::size_v<T>) return std::false_type{}; | |
| 63 | 6 | else return contains_only_(kumi::_::adl_tag, KUMI_FWD(t), kumi::function::indexes_for<T>{}, ids...); | |
| 64 | } | ||
| 65 | }; | ||
| 66 | |||
| 67 | struct contains_none_t : private contains_any_t | ||
| 68 | { | ||
| 69 | template<kumi::concepts::product_type T, kumi::concepts::identifier... Is> | ||
| 70 | [[nodiscard]] KUMI_ABI constexpr auto operator()([[maybe_unused]] T&& t, Is const&... ids) const noexcept | ||
| 71 | { | ||
| 72 | using R = decltype(contains_any_t::operator()(std::declval<T>(), ids...)); | ||
| 73 | 4 | return std::bool_constant<!R{}>{}; | |
| 74 | } | ||
| 75 | }; | ||
| 76 | |||
| 77 | //==================================================================================================================== | ||
| 78 | /** | ||
| 79 | @ingroup kumi_queries | ||
| 80 | |||
| 81 | @var contains | ||
| 82 | @brief Callable object checking if a product type contains a given identifier | ||
| 83 | |||
| 84 | @qualifier nodiscard | ||
| 85 | @qualifier inline | ||
| 86 | @qualifier constexpr | ||
| 87 | @qualifier noexcept | ||
| 88 | |||
| 89 | @groupheader{Header file} | ||
| 90 | @code | ||
| 91 | #include <kumi/algorithm/contains.hpp> | ||
| 92 | @endcode | ||
| 93 | |||
| 94 | @groupheader{Call Signature} | ||
| 95 | |||
| 96 | @code | ||
| 97 | template<product_type T, identifier ID> | ||
| 98 | constexpr auto contains(T && t, ID const& id) noexcept; | ||
| 99 | @endcode | ||
| 100 | |||
| 101 | @subgroupheader{Parameters} | ||
| 102 | |||
| 103 | - `t`: The product type to inspect | ||
| 104 | - `id`: The identifier to check for | ||
| 105 | |||
| 106 | @subgroupheader{Return value} | ||
| 107 | |||
| 108 | - `std::true_type` if `t` contains a field labeled with the `id` identifier, `std::false_type` otherwise. | ||
| 109 | |||
| 110 | @groupheader{Helper type} | ||
| 111 | |||
| 112 | @snippet include/kumi/algorithm/contains.hpp contains_t | ||
| 113 | |||
| 114 | Computes the return type of a call to kumi::contains | ||
| 115 | |||
| 116 | @groupheader{Examples} | ||
| 117 | |||
| 118 | @tab_begin | ||
| 119 | |||
| 120 | @tab{Tuple} | ||
| 121 | @godbolt{doc/tuple/algo/contains.cpp} | ||
| 122 | |||
| 123 | @tab{Record} | ||
| 124 | @godbolt{doc/record/algo/contains.cpp} | ||
| 125 | |||
| 126 | @tab_end | ||
| 127 | **/ | ||
| 128 | //==================================================================================================================== | ||
| 129 | KUMI_VARIABLE_ABI constexpr contains_t contains{}; | ||
| 130 | |||
| 131 | //==================================================================================================================== | ||
| 132 | /** | ||
| 133 | @ingroup kumi_queries | ||
| 134 | |||
| 135 | @var contains_any | ||
| 136 | @brief Callable object checking if a product type contains at least one of many identifier | ||
| 137 | |||
| 138 | @qualifier nodiscard | ||
| 139 | @qualifier inline | ||
| 140 | @qualifier constexpr | ||
| 141 | @qualifier noexcept | ||
| 142 | |||
| 143 | @groupheader{Header file} | ||
| 144 | @code | ||
| 145 | #include <kumi/algorithm/contains.hpp> | ||
| 146 | @endcode | ||
| 147 | |||
| 148 | @groupheader{Call Signature} | ||
| 149 | |||
| 150 | @code | ||
| 151 | template<product_type T, identifier... IDs> | ||
| 152 | constexpr auto contains_any(T && t, IDs const&... ids) noexcept; | ||
| 153 | @endcode | ||
| 154 | |||
| 155 | @subgroupheader{Parameters} | ||
| 156 | |||
| 157 | - `t`: The product type to inspect | ||
| 158 | - `ids`: The identifiers to check for | ||
| 159 | |||
| 160 | @subgroupheader{Return value} | ||
| 161 | |||
| 162 | - `std::true_type` if `t` contains a field labeled with one of the `ids`, `std::false_type` otherwise. | ||
| 163 | |||
| 164 | @groupheader{Helper type} | ||
| 165 | |||
| 166 | @snippet include/kumi/algorithm/contains.hpp contains_any_t | ||
| 167 | |||
| 168 | Computes the return type of a call to kumi::contains_any | ||
| 169 | |||
| 170 | @groupheader{Examples} | ||
| 171 | |||
| 172 | @tab_begin | ||
| 173 | |||
| 174 | @tab{Tuple} | ||
| 175 | @godbolt{doc/tuple/algo/contains_any.cpp} | ||
| 176 | |||
| 177 | @tab{Record} | ||
| 178 | @godbolt{doc/record/algo/contains_any.cpp} | ||
| 179 | |||
| 180 | @tab_end | ||
| 181 | **/ | ||
| 182 | //==================================================================================================================== | ||
| 183 | KUMI_VARIABLE_ABI constexpr contains_any_t contains_any{}; | ||
| 184 | |||
| 185 | //==================================================================================================================== | ||
| 186 | /** | ||
| 187 | @ingroup kumi_queries | ||
| 188 | |||
| 189 | @var contains_only | ||
| 190 | @brief Callable object checking if a product type contains fields based on a selected identifier | ||
| 191 | |||
| 192 | @qualifier nodiscard | ||
| 193 | @qualifier inline | ||
| 194 | @qualifier constexpr | ||
| 195 | @qualifier noexcept | ||
| 196 | |||
| 197 | @groupheader{Header file} | ||
| 198 | @code | ||
| 199 | #include <kumi/algorithm/contains.hpp> | ||
| 200 | @endcode | ||
| 201 | |||
| 202 | @groupheader{Call Signature} | ||
| 203 | |||
| 204 | @code | ||
| 205 | template<product_type T, identifier... IDs> | ||
| 206 | constexpr auto contains_only(T && t, IDs const&... ids) noexcept; | ||
| 207 | @endcode | ||
| 208 | |||
| 209 | @subgroupheader{Parameters} | ||
| 210 | |||
| 211 | - `t`: The product type to inspect | ||
| 212 | - `ids`: The identifiers to check for | ||
| 213 | |||
| 214 | @subgroupheader{Return value} | ||
| 215 | |||
| 216 | - `std::true_type` if `t` contains a field labeled with any of the `ids`, `std::false_type` otherwise. | ||
| 217 | |||
| 218 | @groupheader{Helper type} | ||
| 219 | |||
| 220 | @snippet include/kumi/algorithm/contains.hpp contains_only_t | ||
| 221 | |||
| 222 | Computes the return type of a call to kumi::contains_only | ||
| 223 | |||
| 224 | @groupheader{Examples} | ||
| 225 | |||
| 226 | @tab_begin | ||
| 227 | |||
| 228 | @tab{Tuple} | ||
| 229 | @godbolt{doc/tuple/algo/contains_only.cpp} | ||
| 230 | |||
| 231 | @tab{Record} | ||
| 232 | @godbolt{doc/record/algo/contains_only.cpp} | ||
| 233 | |||
| 234 | @tab_end | ||
| 235 | **/ | ||
| 236 | //==================================================================================================================== | ||
| 237 | KUMI_VARIABLE_ABI constexpr contains_only_t contains_only{}; | ||
| 238 | |||
| 239 | //==================================================================================================================== | ||
| 240 | /** | ||
| 241 | @ingroup kumi_queries | ||
| 242 | |||
| 243 | @var contains_none | ||
| 244 | @brief Callable object checking if a product type contains no fields based on any of the selected identifiers | ||
| 245 | |||
| 246 | @qualifier nodiscard | ||
| 247 | @qualifier inline | ||
| 248 | @qualifier constexpr | ||
| 249 | @qualifier noexcept | ||
| 250 | |||
| 251 | @groupheader{Header file} | ||
| 252 | @code | ||
| 253 | #include <kumi/algorithm/contains.hpp> | ||
| 254 | @endcode | ||
| 255 | |||
| 256 | @groupheader{Call Signature} | ||
| 257 | |||
| 258 | @code | ||
| 259 | template<product_type T, identifier... IDs> | ||
| 260 | constexpr auto contains_none(T && t, IDs const&... ids) noexcept; | ||
| 261 | @endcode | ||
| 262 | |||
| 263 | @subgroupheader{Parameters} | ||
| 264 | |||
| 265 | - `t`: The product type to inspect | ||
| 266 | - `ids`: The identifiers to check for | ||
| 267 | |||
| 268 | @subgroupheader{Return value} | ||
| 269 | |||
| 270 | - `std::true_type` if `t` contains no field labeled with any of the `ids`, `std::false_type` otherwise. | ||
| 271 | |||
| 272 | @groupheader{Helper type} | ||
| 273 | |||
| 274 | @snippet include/kumi/algorithm/contains.hpp contains_none_t | ||
| 275 | |||
| 276 | Computes the return type of a call to kumi::contains_none | ||
| 277 | |||
| 278 | @groupheader{Examples} | ||
| 279 | |||
| 280 | @tab_begin | ||
| 281 | |||
| 282 | @tab{Tuple} | ||
| 283 | @godbolt{doc/tuple/algo/contains_none.cpp} | ||
| 284 | |||
| 285 | @tab{Record} | ||
| 286 | @godbolt{doc/record/algo/contains_none.cpp} | ||
| 287 | |||
| 288 | @tab_end | ||
| 289 | **/ | ||
| 290 | //==================================================================================================================== | ||
| 291 | KUMI_VARIABLE_ABI constexpr contains_none_t contains_none{}; | ||
| 292 | |||
| 293 | namespace result | ||
| 294 | { | ||
| 295 | //! [contains_t] | ||
| 296 | template<kumi::concepts::product_type T, kumi::concepts::identifier ID> | ||
| 297 | using contains_t = decltype(kumi::contains(std::declval<T>(), std::declval<ID>())); | ||
| 298 | |||
| 299 | template<kumi::concepts::product_type T, kumi::concepts::identifier ID> struct contains | ||
| 300 | { | ||
| 301 | using type = kumi::result::contains_t<T, ID>; | ||
| 302 | }; | ||
| 303 | |||
| 304 | //! [contains_t] | ||
| 305 | |||
| 306 | //! [contains_any_t] | ||
| 307 | template<kumi::concepts::product_type T, kumi::concepts::identifier... IDs> | ||
| 308 | using contains_any_t = decltype(kumi::contains_any(std::declval<T>(), std::declval<IDs>()...)); | ||
| 309 | |||
| 310 | template<kumi::concepts::product_type T, kumi::concepts::identifier... IDs> struct contains_any | ||
| 311 | { | ||
| 312 | using type = kumi::result::contains_any_t<T, IDs...>; | ||
| 313 | }; | ||
| 314 | |||
| 315 | //! [contains_any_t] | ||
| 316 | |||
| 317 | //! [contains_only_t] | ||
| 318 | template<kumi::concepts::product_type T, kumi::concepts::identifier... IDs> | ||
| 319 | using contains_only_t = decltype(kumi::contains_only(std::declval<T>(), std::declval<IDs>()...)); | ||
| 320 | |||
| 321 | template<kumi::concepts::product_type T, kumi::concepts::identifier... IDs> struct contains_only | ||
| 322 | { | ||
| 323 | using type = kumi::result::contains_only_t<T, IDs...>; | ||
| 324 | }; | ||
| 325 | |||
| 326 | //! [contains_only_t] | ||
| 327 | |||
| 328 | //! [contains_none_t] | ||
| 329 | template<kumi::concepts::product_type T, kumi::concepts::identifier... IDs> | ||
| 330 | using contains_none_t = decltype(kumi::contains_none(std::declval<T>(), std::declval<IDs>()...)); | ||
| 331 | |||
| 332 | template<kumi::concepts::product_type T, kumi::concepts::identifier... IDs> struct contains_none | ||
| 333 | { | ||
| 334 | using type = kumi::result::contains_none_t<T, IDs...>; | ||
| 335 | }; | ||
| 336 | |||
| 337 | //! [contains_none_t] | ||
| 338 | } | ||
| 339 | } | ||
| 340 |