Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-15 09:53:11

0001 /*!
0002 @file
0003 Defines `boost::hana::type` and related utilities.
0004 
0005 Copyright Louis Dionne 2013-2022
0006 Distributed under the Boost Software License, Version 1.0.
0007 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
0008  */
0009 
0010 #ifndef BOOST_HANA_TYPE_HPP
0011 #define BOOST_HANA_TYPE_HPP
0012 
0013 #include <boost/hana/fwd/type.hpp>
0014 
0015 #include <boost/hana/bool.hpp>
0016 #include <boost/hana/config.hpp>
0017 #include <boost/hana/core/when.hpp>
0018 #include <boost/hana/detail/operators/adl.hpp>
0019 #include <boost/hana/detail/operators/comparable.hpp>
0020 #include <boost/hana/fwd/concept/metafunction.hpp>
0021 #include <boost/hana/fwd/core/make.hpp>
0022 #include <boost/hana/fwd/equal.hpp>
0023 #include <boost/hana/fwd/hash.hpp>
0024 #include <boost/hana/integral_constant.hpp>
0025 
0026 #include <type_traits>
0027 #include <utility>
0028 
0029 
0030 namespace boost { namespace hana {
0031     //////////////////////////////////////////////////////////////////////////
0032     // basic_type
0033     //////////////////////////////////////////////////////////////////////////
0034     //! @cond
0035     template <typename T>
0036     struct basic_type : detail::operators::adl<basic_type<T>> {
0037         using hana_tag = type_tag;
0038 
0039         using type = T;
0040         constexpr auto operator+() const { return *this; }
0041     };
0042     //! @endcond
0043 
0044     //////////////////////////////////////////////////////////////////////////
0045     // type
0046     //////////////////////////////////////////////////////////////////////////
0047     template <typename T>
0048     struct type_impl {
0049         struct _ : basic_type<T> { };
0050     };
0051 
0052     //////////////////////////////////////////////////////////////////////////
0053     // decltype_
0054     //////////////////////////////////////////////////////////////////////////
0055     namespace detail {
0056         template <typename T, typename = type_tag>
0057         struct decltype_t {
0058             using type = typename std::remove_reference<T>::type;
0059         };
0060 
0061         template <typename T>
0062         struct decltype_t<T, typename hana::tag_of<T>::type> {
0063             using type = typename std::remove_reference<T>::type::type;
0064         };
0065     }
0066 
0067     //! @cond
0068     template <typename T>
0069     constexpr auto decltype_t::operator()(T&&) const
0070     { return hana::type_c<typename detail::decltype_t<T>::type>; }
0071     //! @endcond
0072 
0073     //////////////////////////////////////////////////////////////////////////
0074     // typeid_
0075     //////////////////////////////////////////////////////////////////////////
0076     namespace detail {
0077         template <typename T, typename = type_tag>
0078         struct typeid_t {
0079             using type = typename std::remove_cv<
0080                 typename std::remove_reference<T>::type
0081             >::type;
0082         };
0083 
0084         template <typename T>
0085         struct typeid_t<T, typename hana::tag_of<T>::type> {
0086             using type = typename std::remove_reference<T>::type::type;
0087         };
0088     }
0089     //! @cond
0090     template <typename T>
0091     constexpr auto typeid_t::operator()(T&&) const
0092     { return hana::type_c<typename detail::typeid_t<T>::type>; }
0093     //! @endcond
0094 
0095     //////////////////////////////////////////////////////////////////////////
0096     // make<type_tag>
0097     //////////////////////////////////////////////////////////////////////////
0098     template <>
0099     struct make_impl<type_tag> {
0100         template <typename T>
0101         static constexpr auto apply(T&& t)
0102         { return hana::typeid_(static_cast<T&&>(t)); }
0103     };
0104 
0105     //////////////////////////////////////////////////////////////////////////
0106     // sizeof_
0107     //////////////////////////////////////////////////////////////////////////
0108     //! @cond
0109     template <typename T>
0110     constexpr auto sizeof_t::operator()(T&&) const
0111     { return hana::size_c<sizeof(typename detail::decltype_t<T>::type)>; }
0112     //! @endcond
0113 
0114     //////////////////////////////////////////////////////////////////////////
0115     // alignof_
0116     //////////////////////////////////////////////////////////////////////////
0117     //! @cond
0118     template <typename T>
0119     constexpr auto alignof_t::operator()(T&&) const
0120     { return hana::size_c<alignof(typename detail::decltype_t<T>::type)>; }
0121     //! @endcond
0122 
0123     //////////////////////////////////////////////////////////////////////////
0124     // is_valid
0125     //////////////////////////////////////////////////////////////////////////
0126     namespace type_detail {
0127         template <typename F, typename ...Args, typename = decltype(
0128             std::declval<F&&>()(std::declval<Args&&>()...)
0129         )>
0130         constexpr auto is_valid_impl(int) { return hana::true_c; }
0131 
0132         template <typename F, typename ...Args>
0133         constexpr auto is_valid_impl(...) { return hana::false_c; }
0134 
0135         template <typename F>
0136         struct is_valid_fun {
0137             template <typename ...Args>
0138             constexpr auto operator()(Args&& ...) const
0139             { return is_valid_impl<F, Args&&...>(int{}); }
0140         };
0141     }
0142 
0143     //! @cond
0144     template <typename F>
0145     constexpr auto is_valid_t::operator()(F&&) const
0146     { return type_detail::is_valid_fun<F&&>{}; }
0147 
0148     template <typename F, typename ...Args>
0149     constexpr auto is_valid_t::operator()(F&&, Args&& ...) const
0150     { return type_detail::is_valid_impl<F&&, Args&&...>(int{}); }
0151     //! @endcond
0152 
0153     //////////////////////////////////////////////////////////////////////////
0154     // template_
0155     //////////////////////////////////////////////////////////////////////////
0156     // Note: We have to use the very complicated trick below instead of just
0157     // mentionning `F<T...>` in a SFINAE-able context because of CWG 1430
0158     // (http://www.open-std.org/Jtc1/sc22/wg21/docs/cwg_active.html#1430).
0159     namespace template_detail {
0160         template <typename ...T> struct args;
0161         template <typename ...> using always_void = void;
0162 
0163         template <template <typename ...> class F, typename Args, typename = void>
0164         struct specialization_is_valid
0165             : std::false_type
0166         { };
0167 
0168         template <template <typename ...> class F, typename ...T>
0169         struct specialization_is_valid<F, args<T...>, always_void<F<T...>>>
0170             : std::true_type
0171         { };
0172     } // end namespace detail
0173 
0174     template <template <typename ...> class F>
0175     struct template_t {
0176         template <typename ...T>
0177         struct apply {
0178             using type = F<T...>;
0179         };
0180 
0181         template <typename ...T, typename = std::enable_if_t<
0182             template_detail::specialization_is_valid<F, template_detail::args<typename T::type...>>::value
0183         >>
0184         constexpr auto operator()(T const& ...) const
0185         { return hana::type<F<typename T::type...>>{}; }
0186     };
0187 
0188     //////////////////////////////////////////////////////////////////////////
0189     // metafunction
0190     //////////////////////////////////////////////////////////////////////////
0191     template <template <typename ...> class F>
0192     struct metafunction_t {
0193         template <typename ...T>
0194         using apply = F<T...>;
0195 
0196         template <typename ...T>
0197         constexpr hana::type<typename F<typename T::type...>::type>
0198         operator()(T const& ...) const { return {}; }
0199     };
0200 
0201     //////////////////////////////////////////////////////////////////////////
0202     // metafunction_class
0203     //////////////////////////////////////////////////////////////////////////
0204     namespace detail {
0205         template <typename F, typename ...T>
0206         struct always_first { using type = F; };
0207     }
0208     template <typename F>
0209     struct metafunction_class_t {
0210         template <typename ...T>
0211         using apply = typename detail::always_first<F, T...>::type::template apply<T...>;
0212 
0213         template <typename ...T>
0214         constexpr hana::type<typename detail::always_first<F, T...>::type::template apply<typename T::type...>::type>
0215         operator()(T const& ...) const { return {}; }
0216     };
0217 
0218     //////////////////////////////////////////////////////////////////////////
0219     // Metafunction
0220     //////////////////////////////////////////////////////////////////////////
0221     template <template <typename ...> class F>
0222     struct Metafunction<template_t<F>> {
0223         static constexpr bool value = true;
0224     };
0225 
0226     template <template <typename ...> class F>
0227     struct Metafunction<metafunction_t<F>> {
0228         static constexpr bool value = true;
0229     };
0230 
0231     template <typename F>
0232     struct Metafunction<metafunction_class_t<F>> {
0233         static constexpr bool value = true;
0234     };
0235 
0236     //////////////////////////////////////////////////////////////////////////
0237     // integral
0238     //////////////////////////////////////////////////////////////////////////
0239     template <typename F>
0240     struct integral_t {
0241         template <typename ...T, typename Result =
0242             typename detail::always_first<F, T...>::type::template apply<typename T::type...>::type
0243         >
0244         constexpr Result operator()(T const& ...) const {
0245             return Result{};
0246         }
0247     };
0248 
0249     //////////////////////////////////////////////////////////////////////////
0250     // Operators
0251     //////////////////////////////////////////////////////////////////////////
0252     namespace detail {
0253         template <>
0254         struct comparable_operators<type_tag> {
0255             static constexpr bool value = true;
0256         };
0257     }
0258 
0259     //////////////////////////////////////////////////////////////////////////
0260     // Comparable
0261     //////////////////////////////////////////////////////////////////////////
0262     template <>
0263     struct equal_impl<type_tag, type_tag> {
0264         template <typename T, typename U>
0265         static constexpr auto apply(basic_type<T> const&, basic_type<U> const&)
0266         { return hana::false_c; }
0267 
0268         template <typename T>
0269         static constexpr auto apply(basic_type<T> const&, basic_type<T> const&)
0270         { return hana::true_c; }
0271     };
0272 
0273     //////////////////////////////////////////////////////////////////////////
0274     // Hashable
0275     //////////////////////////////////////////////////////////////////////////
0276     template <>
0277     struct hash_impl<hana::type_tag> {
0278         template <typename T>
0279         static constexpr T apply(T const& t)
0280         { return t; }
0281     };
0282 }} // end namespace boost::hana
0283 
0284 #endif // !BOOST_HANA_TYPE_HPP