Home | History | Annotate | Line # | Download | only in std
      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