Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:54:46

0001 /// \file
0002 // Concepts library
0003 //
0004 //  Copyright Eric Niebler 2013-present
0005 //
0006 //  Use, modification and distribution is subject to the
0007 //  Boost Software License, Version 1.0. (See accompanying
0008 //  file LICENSE_1_0.txt or copy at
0009 //  http://www.boost.org/LICENSE_1_0.txt)
0010 //
0011 // Project home: https://github.com/ericniebler/range-v3
0012 
0013 #ifndef CPP_TYPE_TRAITS_HPP
0014 #define CPP_TYPE_TRAITS_HPP
0015 
0016 #include <tuple>
0017 #include <utility>
0018 #include <type_traits>
0019 #include <meta/meta.hpp>
0020 
0021 namespace concepts
0022 {
0023     template<typename T>
0024     using remove_cvref_t =
0025         typename std::remove_cv<
0026             typename std::remove_reference<T>::type>::type;
0027 
0028     /// \cond
0029     namespace detail
0030     {
0031         template<typename From, typename To>
0032         using is_convertible = std::is_convertible<meta::_t<std::add_rvalue_reference<From>>, To>;
0033 
0034         template<bool>
0035         struct if_else_
0036         {
0037             template<typename, typename U>
0038             using invoke = U;
0039         };
0040         template<>
0041         struct if_else_<true>
0042         {
0043             template<typename T, typename>
0044             using invoke = T;
0045         };
0046         template<bool B, typename T, typename U>
0047         using if_else_t = meta::invoke<if_else_<B>, T, U>;
0048 
0049         template<bool>
0050         struct if_
0051         {};
0052         template<>
0053         struct if_<true>
0054         {
0055             template<typename T>
0056             using invoke = T;
0057         };
0058         template<bool B, typename T = void>
0059         using if_t = meta::invoke<if_<B>, T>;
0060 
0061         template<typename From, typename To>
0062         struct _copy_cv_
0063         {
0064             using type = To;
0065         };
0066         template<typename From, typename To>
0067         struct _copy_cv_<From const, To>
0068         {
0069             using type = To const;
0070         };
0071         template<typename From, typename To>
0072         struct _copy_cv_<From volatile, To>
0073         {
0074             using type = To volatile;
0075         };
0076         template<typename From, typename To>
0077         struct _copy_cv_<From const volatile, To>
0078         {
0079             using type = To const volatile;
0080         };
0081         template<typename From, typename To>
0082         using _copy_cv = meta::_t<_copy_cv_<From, To>>;
0083 
0084         ////////////////////////////////////////////////////////////////////////////////////////
0085         template<typename T, typename U, typename = void>
0086         struct _builtin_common;
0087 
0088         template<typename T, typename U>
0089         using _builtin_common_t = meta::_t<_builtin_common<T, U>>;
0090 
0091         template<typename T, typename U>
0092         using _cond_res = decltype(true ? std::declval<T>() : std::declval<U>());
0093 
0094         template<typename T, typename U, typename R = _builtin_common_t<T &, U &>>
0095         using _rref_res =
0096             if_else_t<std::is_reference<R>::value, meta::_t<std::remove_reference<R>> &&, R>;
0097 
0098         template<typename T, typename U>
0099         using _lref_res = _cond_res<_copy_cv<T, U> &, _copy_cv<U, T> &>;
0100 
0101         template<typename T>
0102         struct as_cref_
0103         {
0104             using type = T const &;
0105         };
0106         template<typename T>
0107         struct as_cref_<T &>
0108         {
0109             using type = T const &;
0110         };
0111         template<typename T>
0112         struct as_cref_<T &&>
0113         {
0114             using type = T const &;
0115         };
0116         template<>
0117         struct as_cref_<void>
0118         {
0119             using type = void;
0120         };
0121         template<>
0122         struct as_cref_<void const>
0123         {
0124             using type = void const;
0125         };
0126 
0127         template<typename T>
0128         using as_cref_t = typename as_cref_<T>::type;
0129 
0130         template<typename T>
0131         using decay_t = typename std::decay<T>::type;
0132 
0133     #if !defined(__GNUC__) || defined(__clang__)
0134         template<typename T, typename U, typename = void>
0135         struct _builtin_common_3
0136         {};
0137         template<typename T, typename U>
0138         struct _builtin_common_3<T, U, meta::void_<_cond_res<as_cref_t<T>, as_cref_t<U>>>>
0139             : std::decay<_cond_res<as_cref_t<T>, as_cref_t<U>>>
0140         {};
0141         template<typename T, typename U, typename = void>
0142         struct _builtin_common_2
0143             : _builtin_common_3<T, U>
0144         {};
0145         template<typename T, typename U>
0146         struct _builtin_common_2<T, U, meta::void_<_cond_res<T, U>>>
0147             : std::decay<_cond_res<T, U>>
0148         {};
0149         template<typename T, typename U, typename /* = void */>
0150         struct _builtin_common
0151             : _builtin_common_2<T, U>
0152         {};
0153         template<typename T, typename U>
0154         struct _builtin_common<T &&, U &&, if_t<
0155             is_convertible<T &&, _rref_res<T, U>>::value &&
0156             is_convertible<U &&, _rref_res<T, U>>::value>>
0157         {
0158             using type = _rref_res<T, U>;
0159         };
0160         template<typename T, typename U>
0161         struct _builtin_common<T &, U &>
0162             : meta::defer<_lref_res, T, U>
0163         {};
0164         template<typename T, typename U>
0165         struct _builtin_common<T &, U &&, if_t<
0166             is_convertible<U &&, _builtin_common_t<T &, U const &>>::value>>
0167             : _builtin_common<T &, U const &>
0168         {};
0169         template<typename T, typename U>
0170         struct _builtin_common<T &&, U &>
0171             : _builtin_common<U &, T &&>
0172         {};
0173     #else
0174         template<typename T, typename U, typename = void>
0175         struct _builtin_common_3
0176         {};
0177         template<typename T, typename U>
0178         struct _builtin_common_3<T, U, meta::void_<_cond_res<as_cref_t<T>, as_cref_t<U>>>>
0179             : std::decay<_cond_res<as_cref_t<T>, as_cref_t<U>>>
0180         {};
0181         template<typename T, typename U, typename = void>
0182         struct _builtin_common_2
0183             : _builtin_common_3<T, U>
0184         {};
0185         template<typename T, typename U>
0186         struct _builtin_common_2<T, U, meta::void_<_cond_res<T, U>>>
0187             : std::decay<_cond_res<T, U>>
0188         {};
0189         template<typename T, typename U, typename /* = void */>
0190         struct _builtin_common
0191             : _builtin_common_2<T, U>
0192         {};
0193         template<typename T, typename U, typename = void>
0194         struct _builtin_common_rr
0195             : _builtin_common_2<T &&, U &&>
0196         {};
0197         template<typename T, typename U>
0198         struct _builtin_common_rr<T, U, if_t<
0199             is_convertible<T &&, _rref_res<T, U>>::value &&
0200             is_convertible<U &&, _rref_res<T, U>>::value>>
0201         {
0202             using type = _rref_res<T, U>;
0203         };
0204         template<typename T, typename U>
0205         struct _builtin_common<T &&, U &&>
0206             : _builtin_common_rr<T, U>
0207         {};
0208         template<typename T, typename U>
0209         struct _builtin_common<T &, U &>
0210             : meta::defer<_lref_res, T, U>
0211         {};
0212         template<typename T, typename U, typename = void>
0213         struct _builtin_common_lr
0214             : _builtin_common_2<T &, T &&>
0215         {};
0216         template<typename T, typename U>
0217         struct _builtin_common_lr<T, U, if_t<
0218             is_convertible<U &&, _builtin_common_t<T &, U const &>>::value>>
0219             : _builtin_common<T &, U const &>
0220         {};
0221         template<typename T, typename U>
0222         struct _builtin_common<T &, U &&>
0223             : _builtin_common_lr<T, U>
0224         {};
0225         template<typename T, typename U>
0226         struct _builtin_common<T &&, U &>
0227             : _builtin_common<U &, T &&>
0228         {};
0229     #endif
0230     }
0231     /// \endcond
0232 
0233     /// \addtogroup group-utility Utility
0234     /// @{
0235     ///
0236 
0237     /// Users should specialize this to hook the \c common_with concept
0238     /// until \c std gets a SFINAE-friendly \c std::common_type and there's
0239     /// some sane way to deal with cv and ref qualifiers.
0240     template<typename ...Ts>
0241     struct common_type
0242     {};
0243 
0244     template<typename T>
0245     struct common_type<T>
0246         : std::decay<T>
0247     {};
0248 
0249     template<typename T, typename U>
0250     struct common_type<T, U>
0251         : detail::if_else_t<
0252             (META_IS_SAME(detail::decay_t<T>, T) &&
0253                 META_IS_SAME(detail::decay_t<U>, U) ),
0254             meta::defer<detail::_builtin_common_t, T, U>,
0255             common_type<detail::decay_t<T>, detail::decay_t<U>>>
0256     {};
0257 
0258     template<typename... Ts>
0259     using common_type_t = typename common_type<Ts...>::type;
0260 
0261     template<typename T, typename U, typename... Vs>
0262     struct common_type<T, U, Vs...>
0263         : meta::lazy::fold<meta::list<U, Vs...>, T, meta::quote<common_type_t>>
0264     {};
0265 
0266     /// @}
0267 
0268     /// \addtogroup group-utility Utility
0269     /// @{
0270     ///
0271 
0272     /// Users can specialize this to hook the \c common_reference_with concept.
0273     /// \sa `common_reference`
0274     template<
0275         typename T,
0276         typename U,
0277         template<typename> class TQual,
0278         template<typename> class UQual>
0279     struct basic_common_reference
0280     {};
0281 
0282     /// \cond
0283     namespace detail
0284     {
0285         using _rref =
0286             meta::quote_trait<std::add_rvalue_reference>;
0287         using _lref =
0288             meta::quote_trait<std::add_lvalue_reference>;
0289 
0290         template<typename>
0291         struct _xref
0292         {
0293             template<typename T>
0294             using invoke = T;
0295         };
0296         template<typename T>
0297         struct _xref<T &&>
0298         {
0299             template<typename U>
0300             using invoke =
0301                 meta::_t<std::add_rvalue_reference<meta::invoke<_xref<T>, U>>>;
0302         };
0303         template<typename T>
0304         struct _xref<T &>
0305         {
0306             template<typename U>
0307             using invoke =
0308                 meta::_t<std::add_lvalue_reference<meta::invoke<_xref<T>, U>>>;
0309         };
0310         template<typename T>
0311         struct _xref<T const>
0312         {
0313             template<typename U>
0314             using invoke = U const;
0315         };
0316         template<typename T>
0317         struct _xref<T volatile>
0318         {
0319             template<typename U>
0320             using invoke = U volatile;
0321         };
0322         template<typename T>
0323         struct _xref<T const volatile>
0324         {
0325             template<typename U>
0326             using invoke = U const volatile;
0327         };
0328 
0329         template<typename T, typename U>
0330         using _basic_common_reference =
0331             basic_common_reference<
0332                 remove_cvref_t<T>,
0333                 remove_cvref_t<U>,
0334                 _xref<T>::template invoke,
0335                 _xref<U>::template invoke>;
0336 
0337         template<typename T, typename U, typename = void>
0338         struct _common_reference2
0339             : if_else_t<
0340                 meta::is_trait<_basic_common_reference<T, U>>::value,
0341                 _basic_common_reference<T, U>,
0342                 common_type<T, U>>
0343         {};
0344 
0345         template<typename T, typename U>
0346         struct _common_reference2<T, U, if_t<std::is_reference<_builtin_common_t<T, U>>::value>>
0347             : _builtin_common<T, U>
0348         {};
0349     }
0350     /// \endcond
0351 
0352     /// Users can specialize this to hook the \c common_reference_with concept.
0353     /// \sa `basic_common_reference`
0354     template<typename ...Ts>
0355     struct common_reference
0356     {};
0357 
0358     template<typename T>
0359     struct common_reference<T>
0360     {
0361         using type = T;
0362     };
0363 
0364     template<typename T, typename U>
0365     struct common_reference<T, U>
0366         : detail::_common_reference2<T, U>
0367     {};
0368 
0369     template<typename... Ts>
0370     using common_reference_t = typename common_reference<Ts...>::type;
0371 
0372     template<typename T, typename U, typename... Vs>
0373     struct common_reference<T, U, Vs...>
0374         : meta::lazy::fold<meta::list<U, Vs...>, T, meta::quote<common_reference_t>>
0375     {};
0376     /// @}
0377 } // namespace concepts
0378 
0379 #endif