You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

368 lines
12KB

  1. // <concepts> -*- C++ -*-
  2. // Copyright (C) 2019-2020 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(add_rvalue_reference_t<_From> (&__f)()) {
  57. static_cast<_To>(__f());
  58. };
  59. /// [concept.commonref], concept common_reference_with
  60. template<typename _Tp, typename _Up>
  61. concept common_reference_with
  62. = same_as<common_reference_t<_Tp, _Up>, common_reference_t<_Up, _Tp>>
  63. && convertible_to<_Tp, common_reference_t<_Tp, _Up>>
  64. && convertible_to<_Up, common_reference_t<_Tp, _Up>>;
  65. /// [concept.common], concept common_with
  66. template<typename _Tp, typename _Up>
  67. concept common_with
  68. = same_as<common_type_t<_Tp, _Up>, common_type_t<_Up, _Tp>>
  69. && requires {
  70. static_cast<common_type_t<_Tp, _Up>>(std::declval<_Tp>());
  71. static_cast<common_type_t<_Tp, _Up>>(std::declval<_Up>());
  72. }
  73. && common_reference_with<add_lvalue_reference_t<const _Tp>,
  74. add_lvalue_reference_t<const _Up>>
  75. && common_reference_with<add_lvalue_reference_t<common_type_t<_Tp, _Up>>,
  76. common_reference_t<
  77. add_lvalue_reference_t<const _Tp>,
  78. add_lvalue_reference_t<const _Up>>>;
  79. // [concepts.arithmetic], arithmetic concepts
  80. template<typename _Tp>
  81. concept integral = is_integral_v<_Tp>;
  82. template<typename _Tp>
  83. concept signed_integral = integral<_Tp> && is_signed_v<_Tp>;
  84. template<typename _Tp>
  85. concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>;
  86. template<typename _Tp>
  87. concept floating_point = is_floating_point_v<_Tp>;
  88. namespace __detail
  89. {
  90. template<typename _Tp>
  91. using __cref = const remove_reference_t<_Tp>&;
  92. template<typename _Tp>
  93. concept __class_or_enum
  94. = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>;
  95. } // namespace __detail
  96. /// [concept.assignable], concept assignable_from
  97. template<typename _Lhs, typename _Rhs>
  98. concept assignable_from
  99. = is_lvalue_reference_v<_Lhs>
  100. && common_reference_with<__detail::__cref<_Lhs>, __detail::__cref<_Rhs>>
  101. && requires(_Lhs __lhs, _Rhs&& __rhs) {
  102. { __lhs = static_cast<_Rhs&&>(__rhs) } -> same_as<_Lhs>;
  103. };
  104. /// [concept.destructible], concept destructible
  105. template<typename _Tp>
  106. concept destructible = is_nothrow_destructible_v<_Tp>;
  107. /// [concept.constructible], concept constructible_from
  108. template<typename _Tp, typename... _Args>
  109. concept constructible_from
  110. = destructible<_Tp> && is_constructible_v<_Tp, _Args...>;
  111. /// [concept.defaultinitializable], concept default_initializable
  112. template<typename _Tp>
  113. concept default_initializable = constructible_from<_Tp>
  114. && requires
  115. {
  116. _Tp{};
  117. (void) ::new _Tp;
  118. };
  119. /// [concept.moveconstructible], concept move_constructible
  120. template<typename _Tp>
  121. concept move_constructible
  122. = constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>;
  123. /// [concept.copyconstructible], concept copy_constructible
  124. template<typename _Tp>
  125. concept copy_constructible
  126. = move_constructible<_Tp>
  127. && constructible_from<_Tp, _Tp&> && convertible_to<_Tp&, _Tp>
  128. && constructible_from<_Tp, const _Tp&> && convertible_to<const _Tp&, _Tp>
  129. && constructible_from<_Tp, const _Tp> && convertible_to<const _Tp, _Tp>;
  130. // [concept.swappable], concept swappable
  131. namespace ranges
  132. {
  133. namespace __cust_swap
  134. {
  135. template<typename _Tp> void swap(_Tp&, _Tp&) = delete;
  136. template<typename _Tp, typename _Up>
  137. concept __adl_swap
  138. = (__detail::__class_or_enum<remove_reference_t<_Tp>>
  139. || __detail::__class_or_enum<remove_reference_t<_Up>>)
  140. && requires(_Tp&& __t, _Up&& __u) {
  141. swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u));
  142. };
  143. struct _Swap
  144. {
  145. private:
  146. template<typename _Tp, typename _Up>
  147. static constexpr bool
  148. _S_noexcept()
  149. {
  150. if constexpr (__adl_swap<_Tp, _Up>)
  151. return noexcept(swap(std::declval<_Tp>(), std::declval<_Up>()));
  152. else
  153. return is_nothrow_move_constructible_v<remove_reference_t<_Tp>>
  154. && is_nothrow_move_assignable_v<remove_reference_t<_Tp>>;
  155. }
  156. public:
  157. template<typename _Tp, typename _Up>
  158. requires __adl_swap<_Tp, _Up>
  159. || (same_as<_Tp, _Up> && is_lvalue_reference_v<_Tp>
  160. && move_constructible<remove_reference_t<_Tp>>
  161. && assignable_from<_Tp, remove_reference_t<_Tp>>)
  162. constexpr void
  163. operator()(_Tp&& __t, _Up&& __u) const
  164. noexcept(_S_noexcept<_Tp, _Up>())
  165. {
  166. if constexpr (__adl_swap<_Tp, _Up>)
  167. swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u));
  168. else
  169. {
  170. auto __tmp = static_cast<remove_reference_t<_Tp>&&>(__t);
  171. __t = static_cast<remove_reference_t<_Tp>&&>(__u);
  172. __u = static_cast<remove_reference_t<_Tp>&&>(__tmp);
  173. }
  174. }
  175. template<typename _Tp, typename _Up, size_t _Num>
  176. requires requires(const _Swap& __swap, _Tp& __e1, _Up& __e2) {
  177. __swap(__e1, __e2);
  178. }
  179. constexpr void
  180. operator()(_Tp (&__e1)[_Num], _Up (&__e2)[_Num]) const
  181. noexcept(noexcept(std::declval<const _Swap&>()(*__e1, *__e2)))
  182. {
  183. for (size_t __n = 0; __n < _Num; ++__n)
  184. (*this)(__e1[__n], __e2[__n]);
  185. }
  186. };
  187. } // namespace __cust_swap
  188. inline namespace __cust
  189. {
  190. inline constexpr __cust_swap::_Swap swap{};
  191. } // inline namespace __cust
  192. } // namespace ranges
  193. template<typename _Tp>
  194. concept swappable
  195. = requires(_Tp& __a, _Tp& __b) { ranges::swap(__a, __b); };
  196. template<typename _Tp, typename _Up>
  197. concept swappable_with = common_reference_with<_Tp, _Up>
  198. && requires(_Tp&& __t, _Up&& __u) {
  199. ranges::swap(static_cast<_Tp&&>(__t), static_cast<_Tp&&>(__t));
  200. ranges::swap(static_cast<_Up&&>(__u), static_cast<_Up&&>(__u));
  201. ranges::swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u));
  202. ranges::swap(static_cast<_Up&&>(__u), static_cast<_Tp&&>(__t));
  203. };
  204. // [concepts.object], Object concepts
  205. template<typename _Tp>
  206. concept movable = is_object_v<_Tp> && move_constructible<_Tp>
  207. && assignable_from<_Tp&, _Tp> && swappable<_Tp>;
  208. template<typename _Tp>
  209. concept copyable = copy_constructible<_Tp> && movable<_Tp>
  210. && assignable_from<_Tp&, _Tp&> && assignable_from<_Tp&, const _Tp&>
  211. && assignable_from<_Tp&, const _Tp>;
  212. template<typename _Tp>
  213. concept semiregular = copyable<_Tp> && default_initializable<_Tp>;
  214. // [concepts.compare], comparison concepts
  215. // [concept.booleantestable], Boolean testability
  216. namespace __detail
  217. {
  218. template<typename _Tp>
  219. concept __boolean_testable_impl = convertible_to<_Tp, bool>;
  220. template<typename _Tp>
  221. concept __boolean_testable
  222. = __boolean_testable_impl<_Tp>
  223. && requires(_Tp&& __t)
  224. { { !static_cast<_Tp&&>(__t) } -> __boolean_testable_impl; };
  225. } // namespace __detail
  226. // [concept.equalitycomparable], concept equality_comparable
  227. namespace __detail
  228. {
  229. template<typename _Tp, typename _Up>
  230. concept __weakly_eq_cmp_with
  231. = requires(__detail::__cref<_Tp> __t, __detail::__cref<_Up> __u) {
  232. { __t == __u } -> __boolean_testable;
  233. { __t != __u } -> __boolean_testable;
  234. { __u == __t } -> __boolean_testable;
  235. { __u != __t } -> __boolean_testable;
  236. };
  237. } // namespace __detail
  238. template<typename _Tp>
  239. concept equality_comparable = __detail::__weakly_eq_cmp_with<_Tp, _Tp>;
  240. template<typename _Tp, typename _Up>
  241. concept equality_comparable_with
  242. = equality_comparable<_Tp> && equality_comparable<_Up>
  243. && common_reference_with<__detail::__cref<_Tp>, __detail::__cref<_Up>>
  244. && equality_comparable<common_reference_t<__detail::__cref<_Tp>,
  245. __detail::__cref<_Up>>>
  246. && __detail::__weakly_eq_cmp_with<_Tp, _Up>;
  247. namespace __detail
  248. {
  249. template<typename _Tp, typename _Up>
  250. concept __partially_ordered_with
  251. = requires(const remove_reference_t<_Tp>& __t,
  252. const remove_reference_t<_Up>& __u) {
  253. { __t < __u } -> __boolean_testable;
  254. { __t > __u } -> __boolean_testable;
  255. { __t <= __u } -> __boolean_testable;
  256. { __t >= __u } -> __boolean_testable;
  257. { __u < __t } -> __boolean_testable;
  258. { __u > __t } -> __boolean_testable;
  259. { __u <= __t } -> __boolean_testable;
  260. { __u >= __t } -> __boolean_testable;
  261. };
  262. } // namespace __detail
  263. // [concept.totallyordered], concept totally_ordered
  264. template<typename _Tp>
  265. concept totally_ordered
  266. = equality_comparable<_Tp>
  267. && __detail::__partially_ordered_with<_Tp, _Tp>;
  268. template<typename _Tp, typename _Up>
  269. concept totally_ordered_with
  270. = totally_ordered<_Tp> && totally_ordered<_Up>
  271. && equality_comparable_with<_Tp, _Up>
  272. && totally_ordered<common_reference_t<__detail::__cref<_Tp>,
  273. __detail::__cref<_Up>>>
  274. && __detail::__partially_ordered_with<_Tp, _Up>;
  275. template<typename _Tp>
  276. concept regular = semiregular<_Tp> && equality_comparable<_Tp>;
  277. // [concepts.callable], callable concepts
  278. /// [concept.invocable], concept invocable
  279. template<typename _Fn, typename... _Args>
  280. concept invocable = is_invocable_v<_Fn, _Args...>;
  281. /// [concept.regularinvocable], concept regular_invocable
  282. template<typename _Fn, typename... _Args>
  283. concept regular_invocable = invocable<_Fn, _Args...>;
  284. /// [concept.predicate], concept predicate
  285. template<typename _Fn, typename... _Args>
  286. concept predicate = regular_invocable<_Fn, _Args...>
  287. && __detail::__boolean_testable<invoke_result_t<_Fn, _Args...>>;
  288. /// [concept.relation], concept relation
  289. template<typename _Rel, typename _Tp, typename _Up>
  290. concept relation
  291. = predicate<_Rel, _Tp, _Tp> && predicate<_Rel, _Up, _Up>
  292. && predicate<_Rel, _Tp, _Up> && predicate<_Rel, _Up, _Tp>;
  293. /// [concept.equiv], concept equivalence_relation
  294. template<typename _Rel, typename _Tp, typename _Up>
  295. concept equivalence_relation = relation<_Rel, _Tp, _Up>;
  296. /// [concept.strictweakorder], concept strict_weak_order
  297. template<typename _Rel, typename _Tp, typename _Up>
  298. concept strict_weak_order = relation<_Rel, _Tp, _Up>;
  299. _GLIBCXX_END_NAMESPACE_VERSION
  300. } // namespace
  301. #endif // C++2a
  302. #endif /* _GLIBCXX_CONCEPTS */