concepts 12 KB

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