1 1.1 mrg // <concepts> -*- C++ -*- 2 1.1 mrg 3 1.1.1.2 mrg // Copyright (C) 2019-2022 Free Software Foundation, Inc. 4 1.1 mrg // 5 1.1 mrg // This file is part of the GNU ISO C++ Library. This library is free 6 1.1 mrg // software; you can redistribute it and/or modify it under the 7 1.1 mrg // terms of the GNU General Public License as published by the 8 1.1 mrg // Free Software Foundation; either version 3, or (at your option) 9 1.1 mrg // any later version. 10 1.1 mrg 11 1.1 mrg // This library is distributed in the hope that it will be useful, 12 1.1 mrg // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 mrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 1.1 mrg // GNU General Public License for more details. 15 1.1 mrg 16 1.1 mrg // Under Section 7 of GPL version 3, you are granted additional 17 1.1 mrg // permissions described in the GCC Runtime Library Exception, version 18 1.1 mrg // 3.1, as published by the Free Software Foundation. 19 1.1 mrg 20 1.1 mrg // You should have received a copy of the GNU General Public License and 21 1.1 mrg // a copy of the GCC Runtime Library Exception along with this program; 22 1.1 mrg // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 1.1 mrg // <http://www.gnu.org/licenses/>. 24 1.1 mrg 25 1.1 mrg /** @file include/concepts 26 1.1 mrg * This is a Standard C++ Library header. 27 1.1 mrg * @ingroup concepts 28 1.1 mrg */ 29 1.1 mrg 30 1.1 mrg #ifndef _GLIBCXX_CONCEPTS 31 1.1 mrg #define _GLIBCXX_CONCEPTS 1 32 1.1 mrg 33 1.1 mrg #if __cplusplus > 201703L && __cpp_concepts >= 201907L 34 1.1 mrg 35 1.1 mrg #pragma GCC system_header 36 1.1 mrg 37 1.1 mrg /** 38 1.1 mrg * @defgroup concepts Concepts 39 1.1 mrg * @ingroup utilities 40 1.1 mrg * 41 1.1 mrg * Concepts for checking type requirements. 42 1.1 mrg */ 43 1.1 mrg 44 1.1 mrg #include <type_traits> 45 1.1 mrg 46 1.1 mrg namespace std _GLIBCXX_VISIBILITY(default) 47 1.1 mrg { 48 1.1 mrg _GLIBCXX_BEGIN_NAMESPACE_VERSION 49 1.1 mrg 50 1.1 mrg #define __cpp_lib_concepts 202002L 51 1.1 mrg 52 1.1 mrg // [concepts.lang], language-related concepts 53 1.1 mrg 54 1.1 mrg namespace __detail 55 1.1 mrg { 56 1.1 mrg template<typename _Tp, typename _Up> 57 1.1 mrg concept __same_as = std::is_same_v<_Tp, _Up>; 58 1.1 mrg } // namespace __detail 59 1.1 mrg 60 1.1 mrg /// [concept.same], concept same_as 61 1.1 mrg template<typename _Tp, typename _Up> 62 1.1 mrg concept same_as 63 1.1 mrg = __detail::__same_as<_Tp, _Up> && __detail::__same_as<_Up, _Tp>; 64 1.1 mrg 65 1.1 mrg /// [concept.derived], concept derived_from 66 1.1 mrg template<typename _Derived, typename _Base> 67 1.1 mrg concept derived_from = __is_base_of(_Base, _Derived) 68 1.1 mrg && is_convertible_v<const volatile _Derived*, const volatile _Base*>; 69 1.1 mrg 70 1.1 mrg /// [concept.convertible], concept convertible_to 71 1.1 mrg template<typename _From, typename _To> 72 1.1 mrg concept convertible_to = is_convertible_v<_From, _To> 73 1.1 mrg && requires { static_cast<_To>(std::declval<_From>()); }; 74 1.1 mrg 75 1.1 mrg /// [concept.commonref], concept common_reference_with 76 1.1 mrg template<typename _Tp, typename _Up> 77 1.1 mrg concept common_reference_with 78 1.1 mrg = same_as<common_reference_t<_Tp, _Up>, common_reference_t<_Up, _Tp>> 79 1.1 mrg && convertible_to<_Tp, common_reference_t<_Tp, _Up>> 80 1.1 mrg && convertible_to<_Up, common_reference_t<_Tp, _Up>>; 81 1.1 mrg 82 1.1 mrg /// [concept.common], concept common_with 83 1.1 mrg template<typename _Tp, typename _Up> 84 1.1 mrg concept common_with 85 1.1 mrg = same_as<common_type_t<_Tp, _Up>, common_type_t<_Up, _Tp>> 86 1.1 mrg && requires { 87 1.1 mrg static_cast<common_type_t<_Tp, _Up>>(std::declval<_Tp>()); 88 1.1 mrg static_cast<common_type_t<_Tp, _Up>>(std::declval<_Up>()); 89 1.1 mrg } 90 1.1 mrg && common_reference_with<add_lvalue_reference_t<const _Tp>, 91 1.1 mrg add_lvalue_reference_t<const _Up>> 92 1.1 mrg && common_reference_with<add_lvalue_reference_t<common_type_t<_Tp, _Up>>, 93 1.1 mrg common_reference_t< 94 1.1 mrg add_lvalue_reference_t<const _Tp>, 95 1.1 mrg add_lvalue_reference_t<const _Up>>>; 96 1.1 mrg 97 1.1 mrg // [concepts.arithmetic], arithmetic concepts 98 1.1 mrg 99 1.1 mrg template<typename _Tp> 100 1.1 mrg concept integral = is_integral_v<_Tp>; 101 1.1 mrg 102 1.1 mrg template<typename _Tp> 103 1.1 mrg concept signed_integral = integral<_Tp> && is_signed_v<_Tp>; 104 1.1 mrg 105 1.1 mrg template<typename _Tp> 106 1.1 mrg concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>; 107 1.1 mrg 108 1.1 mrg template<typename _Tp> 109 1.1 mrg concept floating_point = is_floating_point_v<_Tp>; 110 1.1 mrg 111 1.1 mrg namespace __detail 112 1.1 mrg { 113 1.1 mrg template<typename _Tp> 114 1.1 mrg using __cref = const remove_reference_t<_Tp>&; 115 1.1 mrg 116 1.1 mrg template<typename _Tp> 117 1.1 mrg concept __class_or_enum 118 1.1 mrg = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>; 119 1.1 mrg } // namespace __detail 120 1.1 mrg 121 1.1 mrg /// [concept.assignable], concept assignable_from 122 1.1 mrg template<typename _Lhs, typename _Rhs> 123 1.1 mrg concept assignable_from 124 1.1 mrg = is_lvalue_reference_v<_Lhs> 125 1.1 mrg && common_reference_with<__detail::__cref<_Lhs>, __detail::__cref<_Rhs>> 126 1.1 mrg && requires(_Lhs __lhs, _Rhs&& __rhs) { 127 1.1 mrg { __lhs = static_cast<_Rhs&&>(__rhs) } -> same_as<_Lhs>; 128 1.1 mrg }; 129 1.1 mrg 130 1.1 mrg /// [concept.destructible], concept destructible 131 1.1 mrg template<typename _Tp> 132 1.1 mrg concept destructible = is_nothrow_destructible_v<_Tp>; 133 1.1 mrg 134 1.1 mrg /// [concept.constructible], concept constructible_from 135 1.1 mrg template<typename _Tp, typename... _Args> 136 1.1 mrg concept constructible_from 137 1.1 mrg = destructible<_Tp> && is_constructible_v<_Tp, _Args...>; 138 1.1 mrg 139 1.1 mrg /// [concept.defaultinitializable], concept default_initializable 140 1.1 mrg template<typename _Tp> 141 1.1 mrg concept default_initializable = constructible_from<_Tp> 142 1.1 mrg && requires 143 1.1 mrg { 144 1.1 mrg _Tp{}; 145 1.1 mrg (void) ::new _Tp; 146 1.1 mrg }; 147 1.1 mrg 148 1.1 mrg /// [concept.moveconstructible], concept move_constructible 149 1.1 mrg template<typename _Tp> 150 1.1 mrg concept move_constructible 151 1.1 mrg = constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>; 152 1.1 mrg 153 1.1 mrg /// [concept.copyconstructible], concept copy_constructible 154 1.1 mrg template<typename _Tp> 155 1.1 mrg concept copy_constructible 156 1.1 mrg = move_constructible<_Tp> 157 1.1 mrg && constructible_from<_Tp, _Tp&> && convertible_to<_Tp&, _Tp> 158 1.1 mrg && constructible_from<_Tp, const _Tp&> && convertible_to<const _Tp&, _Tp> 159 1.1 mrg && constructible_from<_Tp, const _Tp> && convertible_to<const _Tp, _Tp>; 160 1.1 mrg 161 1.1 mrg // [concept.swappable], concept swappable 162 1.1 mrg 163 1.1 mrg namespace ranges 164 1.1 mrg { 165 1.1 mrg namespace __cust_swap 166 1.1 mrg { 167 1.1 mrg template<typename _Tp> void swap(_Tp&, _Tp&) = delete; 168 1.1 mrg 169 1.1 mrg template<typename _Tp, typename _Up> 170 1.1 mrg concept __adl_swap 171 1.1 mrg = (__detail::__class_or_enum<remove_reference_t<_Tp>> 172 1.1 mrg || __detail::__class_or_enum<remove_reference_t<_Up>>) 173 1.1 mrg && requires(_Tp&& __t, _Up&& __u) { 174 1.1 mrg swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); 175 1.1 mrg }; 176 1.1 mrg 177 1.1 mrg struct _Swap 178 1.1 mrg { 179 1.1 mrg private: 180 1.1 mrg template<typename _Tp, typename _Up> 181 1.1 mrg static constexpr bool 182 1.1 mrg _S_noexcept() 183 1.1 mrg { 184 1.1 mrg if constexpr (__adl_swap<_Tp, _Up>) 185 1.1 mrg return noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())); 186 1.1 mrg else 187 1.1 mrg return is_nothrow_move_constructible_v<remove_reference_t<_Tp>> 188 1.1 mrg && is_nothrow_move_assignable_v<remove_reference_t<_Tp>>; 189 1.1 mrg } 190 1.1 mrg 191 1.1 mrg public: 192 1.1 mrg template<typename _Tp, typename _Up> 193 1.1 mrg requires __adl_swap<_Tp, _Up> 194 1.1 mrg || (same_as<_Tp, _Up> && is_lvalue_reference_v<_Tp> 195 1.1 mrg && move_constructible<remove_reference_t<_Tp>> 196 1.1 mrg && assignable_from<_Tp, remove_reference_t<_Tp>>) 197 1.1 mrg constexpr void 198 1.1 mrg operator()(_Tp&& __t, _Up&& __u) const 199 1.1 mrg noexcept(_S_noexcept<_Tp, _Up>()) 200 1.1 mrg { 201 1.1 mrg if constexpr (__adl_swap<_Tp, _Up>) 202 1.1 mrg swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); 203 1.1 mrg else 204 1.1 mrg { 205 1.1 mrg auto __tmp = static_cast<remove_reference_t<_Tp>&&>(__t); 206 1.1 mrg __t = static_cast<remove_reference_t<_Tp>&&>(__u); 207 1.1 mrg __u = static_cast<remove_reference_t<_Tp>&&>(__tmp); 208 1.1 mrg } 209 1.1 mrg } 210 1.1 mrg 211 1.1 mrg template<typename _Tp, typename _Up, size_t _Num> 212 1.1 mrg requires requires(const _Swap& __swap, _Tp& __e1, _Up& __e2) { 213 1.1 mrg __swap(__e1, __e2); 214 1.1 mrg } 215 1.1 mrg constexpr void 216 1.1 mrg operator()(_Tp (&__e1)[_Num], _Up (&__e2)[_Num]) const 217 1.1 mrg noexcept(noexcept(std::declval<const _Swap&>()(*__e1, *__e2))) 218 1.1 mrg { 219 1.1 mrg for (size_t __n = 0; __n < _Num; ++__n) 220 1.1 mrg (*this)(__e1[__n], __e2[__n]); 221 1.1 mrg } 222 1.1 mrg }; 223 1.1 mrg } // namespace __cust_swap 224 1.1 mrg 225 1.1 mrg inline namespace __cust 226 1.1 mrg { 227 1.1 mrg inline constexpr __cust_swap::_Swap swap{}; 228 1.1 mrg } // inline namespace __cust 229 1.1 mrg } // namespace ranges 230 1.1 mrg 231 1.1 mrg template<typename _Tp> 232 1.1 mrg concept swappable 233 1.1 mrg = requires(_Tp& __a, _Tp& __b) { ranges::swap(__a, __b); }; 234 1.1 mrg 235 1.1 mrg template<typename _Tp, typename _Up> 236 1.1 mrg concept swappable_with = common_reference_with<_Tp, _Up> 237 1.1 mrg && requires(_Tp&& __t, _Up&& __u) { 238 1.1 mrg ranges::swap(static_cast<_Tp&&>(__t), static_cast<_Tp&&>(__t)); 239 1.1 mrg ranges::swap(static_cast<_Up&&>(__u), static_cast<_Up&&>(__u)); 240 1.1 mrg ranges::swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); 241 1.1 mrg ranges::swap(static_cast<_Up&&>(__u), static_cast<_Tp&&>(__t)); 242 1.1 mrg }; 243 1.1 mrg 244 1.1 mrg // [concepts.object], Object concepts 245 1.1 mrg 246 1.1 mrg template<typename _Tp> 247 1.1 mrg concept movable = is_object_v<_Tp> && move_constructible<_Tp> 248 1.1 mrg && assignable_from<_Tp&, _Tp> && swappable<_Tp>; 249 1.1 mrg 250 1.1 mrg template<typename _Tp> 251 1.1 mrg concept copyable = copy_constructible<_Tp> && movable<_Tp> 252 1.1 mrg && assignable_from<_Tp&, _Tp&> && assignable_from<_Tp&, const _Tp&> 253 1.1 mrg && assignable_from<_Tp&, const _Tp>; 254 1.1 mrg 255 1.1 mrg template<typename _Tp> 256 1.1 mrg concept semiregular = copyable<_Tp> && default_initializable<_Tp>; 257 1.1 mrg 258 1.1 mrg // [concepts.compare], comparison concepts 259 1.1 mrg 260 1.1 mrg // [concept.booleantestable], Boolean testability 261 1.1 mrg namespace __detail 262 1.1 mrg { 263 1.1 mrg template<typename _Tp> 264 1.1 mrg concept __boolean_testable_impl = convertible_to<_Tp, bool>; 265 1.1 mrg 266 1.1 mrg template<typename _Tp> 267 1.1 mrg concept __boolean_testable 268 1.1 mrg = __boolean_testable_impl<_Tp> 269 1.1 mrg && requires(_Tp&& __t) 270 1.1 mrg { { !static_cast<_Tp&&>(__t) } -> __boolean_testable_impl; }; 271 1.1 mrg } // namespace __detail 272 1.1 mrg 273 1.1 mrg // [concept.equalitycomparable], concept equality_comparable 274 1.1 mrg 275 1.1 mrg namespace __detail 276 1.1 mrg { 277 1.1 mrg template<typename _Tp, typename _Up> 278 1.1 mrg concept __weakly_eq_cmp_with 279 1.1 mrg = requires(__detail::__cref<_Tp> __t, __detail::__cref<_Up> __u) { 280 1.1 mrg { __t == __u } -> __boolean_testable; 281 1.1 mrg { __t != __u } -> __boolean_testable; 282 1.1 mrg { __u == __t } -> __boolean_testable; 283 1.1 mrg { __u != __t } -> __boolean_testable; 284 1.1 mrg }; 285 1.1 mrg } // namespace __detail 286 1.1 mrg 287 1.1 mrg template<typename _Tp> 288 1.1 mrg concept equality_comparable = __detail::__weakly_eq_cmp_with<_Tp, _Tp>; 289 1.1 mrg 290 1.1 mrg template<typename _Tp, typename _Up> 291 1.1 mrg concept equality_comparable_with 292 1.1 mrg = equality_comparable<_Tp> && equality_comparable<_Up> 293 1.1 mrg && common_reference_with<__detail::__cref<_Tp>, __detail::__cref<_Up>> 294 1.1 mrg && equality_comparable<common_reference_t<__detail::__cref<_Tp>, 295 1.1 mrg __detail::__cref<_Up>>> 296 1.1 mrg && __detail::__weakly_eq_cmp_with<_Tp, _Up>; 297 1.1 mrg 298 1.1 mrg namespace __detail 299 1.1 mrg { 300 1.1 mrg template<typename _Tp, typename _Up> 301 1.1 mrg concept __partially_ordered_with 302 1.1 mrg = requires(const remove_reference_t<_Tp>& __t, 303 1.1 mrg const remove_reference_t<_Up>& __u) { 304 1.1 mrg { __t < __u } -> __boolean_testable; 305 1.1 mrg { __t > __u } -> __boolean_testable; 306 1.1 mrg { __t <= __u } -> __boolean_testable; 307 1.1 mrg { __t >= __u } -> __boolean_testable; 308 1.1 mrg { __u < __t } -> __boolean_testable; 309 1.1 mrg { __u > __t } -> __boolean_testable; 310 1.1 mrg { __u <= __t } -> __boolean_testable; 311 1.1 mrg { __u >= __t } -> __boolean_testable; 312 1.1 mrg }; 313 1.1 mrg } // namespace __detail 314 1.1 mrg 315 1.1 mrg // [concept.totallyordered], concept totally_ordered 316 1.1 mrg template<typename _Tp> 317 1.1 mrg concept totally_ordered 318 1.1 mrg = equality_comparable<_Tp> 319 1.1 mrg && __detail::__partially_ordered_with<_Tp, _Tp>; 320 1.1 mrg 321 1.1 mrg template<typename _Tp, typename _Up> 322 1.1 mrg concept totally_ordered_with 323 1.1 mrg = totally_ordered<_Tp> && totally_ordered<_Up> 324 1.1 mrg && equality_comparable_with<_Tp, _Up> 325 1.1 mrg && totally_ordered<common_reference_t<__detail::__cref<_Tp>, 326 1.1 mrg __detail::__cref<_Up>>> 327 1.1 mrg && __detail::__partially_ordered_with<_Tp, _Up>; 328 1.1 mrg 329 1.1 mrg template<typename _Tp> 330 1.1 mrg concept regular = semiregular<_Tp> && equality_comparable<_Tp>; 331 1.1 mrg 332 1.1 mrg // [concepts.callable], callable concepts 333 1.1 mrg 334 1.1 mrg /// [concept.invocable], concept invocable 335 1.1 mrg template<typename _Fn, typename... _Args> 336 1.1 mrg concept invocable = is_invocable_v<_Fn, _Args...>; 337 1.1 mrg 338 1.1 mrg /// [concept.regularinvocable], concept regular_invocable 339 1.1 mrg template<typename _Fn, typename... _Args> 340 1.1 mrg concept regular_invocable = invocable<_Fn, _Args...>; 341 1.1 mrg 342 1.1 mrg /// [concept.predicate], concept predicate 343 1.1 mrg template<typename _Fn, typename... _Args> 344 1.1 mrg concept predicate = regular_invocable<_Fn, _Args...> 345 1.1 mrg && __detail::__boolean_testable<invoke_result_t<_Fn, _Args...>>; 346 1.1 mrg 347 1.1 mrg /// [concept.relation], concept relation 348 1.1 mrg template<typename _Rel, typename _Tp, typename _Up> 349 1.1 mrg concept relation 350 1.1 mrg = predicate<_Rel, _Tp, _Tp> && predicate<_Rel, _Up, _Up> 351 1.1 mrg && predicate<_Rel, _Tp, _Up> && predicate<_Rel, _Up, _Tp>; 352 1.1 mrg 353 1.1 mrg /// [concept.equiv], concept equivalence_relation 354 1.1 mrg template<typename _Rel, typename _Tp, typename _Up> 355 1.1 mrg concept equivalence_relation = relation<_Rel, _Tp, _Up>; 356 1.1 mrg 357 1.1 mrg /// [concept.strictweakorder], concept strict_weak_order 358 1.1 mrg template<typename _Rel, typename _Tp, typename _Up> 359 1.1 mrg concept strict_weak_order = relation<_Rel, _Tp, _Up>; 360 1.1 mrg 361 1.1 mrg _GLIBCXX_END_NAMESPACE_VERSION 362 1.1 mrg } // namespace 363 1.1 mrg #endif // C++2a 364 1.1 mrg 365 1.1 mrg #endif /* _GLIBCXX_CONCEPTS */ 366