123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- /*!
- @file
- Defines `boost::hana::type` and related utilities.
- Copyright Louis Dionne 2013-2022
- Distributed under the Boost Software License, Version 1.0.
- (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
- */
- #ifndef BOOST_HANA_TYPE_HPP
- #define BOOST_HANA_TYPE_HPP
- #include <boost/hana/fwd/type.hpp>
- #include <boost/hana/bool.hpp>
- #include <boost/hana/config.hpp>
- #include <boost/hana/core/when.hpp>
- #include <boost/hana/detail/operators/adl.hpp>
- #include <boost/hana/detail/operators/comparable.hpp>
- #include <boost/hana/fwd/concept/metafunction.hpp>
- #include <boost/hana/fwd/core/make.hpp>
- #include <boost/hana/fwd/equal.hpp>
- #include <boost/hana/fwd/hash.hpp>
- #include <boost/hana/integral_constant.hpp>
- #include <type_traits>
- #include <utility>
- namespace boost { namespace hana {
- //////////////////////////////////////////////////////////////////////////
- // basic_type
- //////////////////////////////////////////////////////////////////////////
- //! @cond
- template <typename T>
- struct basic_type : detail::operators::adl<basic_type<T>> {
- using hana_tag = type_tag;
- using type = T;
- constexpr auto operator+() const { return *this; }
- };
- //! @endcond
- //////////////////////////////////////////////////////////////////////////
- // type
- //////////////////////////////////////////////////////////////////////////
- template <typename T>
- struct type_impl {
- struct _ : basic_type<T> { };
- };
- //////////////////////////////////////////////////////////////////////////
- // decltype_
- //////////////////////////////////////////////////////////////////////////
- namespace detail {
- template <typename T, typename = type_tag>
- struct decltype_t {
- using type = typename std::remove_reference<T>::type;
- };
- template <typename T>
- struct decltype_t<T, typename hana::tag_of<T>::type> {
- using type = typename std::remove_reference<T>::type::type;
- };
- }
- //! @cond
- template <typename T>
- constexpr auto decltype_t::operator()(T&&) const
- { return hana::type_c<typename detail::decltype_t<T>::type>; }
- //! @endcond
- //////////////////////////////////////////////////////////////////////////
- // typeid_
- //////////////////////////////////////////////////////////////////////////
- namespace detail {
- template <typename T, typename = type_tag>
- struct typeid_t {
- using type = typename std::remove_cv<
- typename std::remove_reference<T>::type
- >::type;
- };
- template <typename T>
- struct typeid_t<T, typename hana::tag_of<T>::type> {
- using type = typename std::remove_reference<T>::type::type;
- };
- }
- //! @cond
- template <typename T>
- constexpr auto typeid_t::operator()(T&&) const
- { return hana::type_c<typename detail::typeid_t<T>::type>; }
- //! @endcond
- //////////////////////////////////////////////////////////////////////////
- // make<type_tag>
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct make_impl<type_tag> {
- template <typename T>
- static constexpr auto apply(T&& t)
- { return hana::typeid_(static_cast<T&&>(t)); }
- };
- //////////////////////////////////////////////////////////////////////////
- // sizeof_
- //////////////////////////////////////////////////////////////////////////
- //! @cond
- template <typename T>
- constexpr auto sizeof_t::operator()(T&&) const
- { return hana::size_c<sizeof(typename detail::decltype_t<T>::type)>; }
- //! @endcond
- //////////////////////////////////////////////////////////////////////////
- // alignof_
- //////////////////////////////////////////////////////////////////////////
- //! @cond
- template <typename T>
- constexpr auto alignof_t::operator()(T&&) const
- { return hana::size_c<alignof(typename detail::decltype_t<T>::type)>; }
- //! @endcond
- //////////////////////////////////////////////////////////////////////////
- // is_valid
- //////////////////////////////////////////////////////////////////////////
- namespace type_detail {
- template <typename F, typename ...Args, typename = decltype(
- std::declval<F&&>()(std::declval<Args&&>()...)
- )>
- constexpr auto is_valid_impl(int) { return hana::true_c; }
- template <typename F, typename ...Args>
- constexpr auto is_valid_impl(...) { return hana::false_c; }
- template <typename F>
- struct is_valid_fun {
- template <typename ...Args>
- constexpr auto operator()(Args&& ...) const
- { return is_valid_impl<F, Args&&...>(int{}); }
- };
- }
- //! @cond
- template <typename F>
- constexpr auto is_valid_t::operator()(F&&) const
- { return type_detail::is_valid_fun<F&&>{}; }
- template <typename F, typename ...Args>
- constexpr auto is_valid_t::operator()(F&&, Args&& ...) const
- { return type_detail::is_valid_impl<F&&, Args&&...>(int{}); }
- //! @endcond
- //////////////////////////////////////////////////////////////////////////
- // template_
- //////////////////////////////////////////////////////////////////////////
- // Note: We have to use the very complicated trick below instead of just
- // mentionning `F<T...>` in a SFINAE-able context because of CWG 1430
- // (http://www.open-std.org/Jtc1/sc22/wg21/docs/cwg_active.html#1430).
- namespace template_detail {
- template <typename ...T> struct args;
- template <typename ...> using always_void = void;
- template <template <typename ...> class F, typename Args, typename = void>
- struct specialization_is_valid
- : std::false_type
- { };
- template <template <typename ...> class F, typename ...T>
- struct specialization_is_valid<F, args<T...>, always_void<F<T...>>>
- : std::true_type
- { };
- } // end namespace detail
- template <template <typename ...> class F>
- struct template_t {
- template <typename ...T>
- struct apply {
- using type = F<T...>;
- };
- template <typename ...T, typename = std::enable_if_t<
- template_detail::specialization_is_valid<F, template_detail::args<typename T::type...>>::value
- >>
- constexpr auto operator()(T const& ...) const
- { return hana::type<F<typename T::type...>>{}; }
- };
- //////////////////////////////////////////////////////////////////////////
- // metafunction
- //////////////////////////////////////////////////////////////////////////
- template <template <typename ...> class F>
- struct metafunction_t {
- template <typename ...T>
- using apply = F<T...>;
- template <typename ...T>
- constexpr hana::type<typename F<typename T::type...>::type>
- operator()(T const& ...) const { return {}; }
- };
- //////////////////////////////////////////////////////////////////////////
- // metafunction_class
- //////////////////////////////////////////////////////////////////////////
- namespace detail {
- template <typename F, typename ...T>
- struct always_first { using type = F; };
- }
- template <typename F>
- struct metafunction_class_t {
- template <typename ...T>
- using apply = typename detail::always_first<F, T...>::type::template apply<T...>;
- template <typename ...T>
- constexpr hana::type<typename detail::always_first<F, T...>::type::template apply<typename T::type...>::type>
- operator()(T const& ...) const { return {}; }
- };
- //////////////////////////////////////////////////////////////////////////
- // Metafunction
- //////////////////////////////////////////////////////////////////////////
- template <template <typename ...> class F>
- struct Metafunction<template_t<F>> {
- static constexpr bool value = true;
- };
- template <template <typename ...> class F>
- struct Metafunction<metafunction_t<F>> {
- static constexpr bool value = true;
- };
- template <typename F>
- struct Metafunction<metafunction_class_t<F>> {
- static constexpr bool value = true;
- };
- //////////////////////////////////////////////////////////////////////////
- // integral
- //////////////////////////////////////////////////////////////////////////
- template <typename F>
- struct integral_t {
- template <typename ...T, typename Result =
- typename detail::always_first<F, T...>::type::template apply<typename T::type...>::type
- >
- constexpr Result operator()(T const& ...) const {
- return Result{};
- }
- };
- //////////////////////////////////////////////////////////////////////////
- // Operators
- //////////////////////////////////////////////////////////////////////////
- namespace detail {
- template <>
- struct comparable_operators<type_tag> {
- static constexpr bool value = true;
- };
- }
- //////////////////////////////////////////////////////////////////////////
- // Comparable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct equal_impl<type_tag, type_tag> {
- template <typename T, typename U>
- static constexpr auto apply(basic_type<T> const&, basic_type<U> const&)
- { return hana::false_c; }
- template <typename T>
- static constexpr auto apply(basic_type<T> const&, basic_type<T> const&)
- { return hana::true_c; }
- };
- //////////////////////////////////////////////////////////////////////////
- // Hashable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct hash_impl<hana::type_tag> {
- template <typename T>
- static constexpr T apply(T const& t)
- { return t; }
- };
- }} // end namespace boost::hana
- #endif // !BOOST_HANA_TYPE_HPP
|