1 /*! 2 @file 3 Defines `boost::hana::experimental::types`. 4 5 @copyright Louis Dionne 2013-2017 6 Distributed under the Boost Software License, Version 1.0. 7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 8 */ 9 10 #ifndef BOOST_HANA_EXPERIMENTAL_TYPES_HPP 11 #define BOOST_HANA_EXPERIMENTAL_TYPES_HPP 12 13 #include <boost/hana/bool.hpp> 14 #include <boost/hana/concept/metafunction.hpp> 15 #include <boost/hana/config.hpp> 16 #include <boost/hana/detail/any_of.hpp> 17 #include <boost/hana/detail/type_at.hpp> 18 #include <boost/hana/fwd/at.hpp> 19 #include <boost/hana/fwd/contains.hpp> 20 #include <boost/hana/fwd/core/tag_of.hpp> 21 #include <boost/hana/fwd/equal.hpp> 22 #include <boost/hana/fwd/is_empty.hpp> 23 #include <boost/hana/fwd/transform.hpp> 24 #include <boost/hana/fwd/unpack.hpp> 25 #include <boost/hana/type.hpp> 26 27 #include <cstddef> 28 #include <type_traits> 29 #include <utility> 30 31 32 BOOST_HANA_NAMESPACE_BEGIN 33 namespace experimental { 34 //! @ingroup group-experimental 35 //! Container optimized for holding types. 36 //! 37 //! It is often useful to manipulate a sequence that contains types 38 //! only, without any associated runtime value. This container allows 39 //! storing and manipulating pure types in a much more compile-time 40 //! efficient manner than using `hana::tuple`, which must assume that 41 //! its contents might have runtime values. 42 template <typename ...T> 43 struct types; 44 45 struct types_tag; 46 47 template <typename ...T> 48 struct types { }; 49 } // end namespace experimental 50 51 template <typename ...T> 52 struct tag_of<experimental::types<T...>> { 53 using type = experimental::types_tag; 54 }; 55 56 // Foldable 57 template <> 58 struct unpack_impl<hana::experimental::types_tag> { 59 template <typename ...T, typename F, typename = typename std::enable_if< 60 !hana::Metafunction<F>::value 61 >::type> applyunpack_impl62 static constexpr decltype(auto) apply(hana::experimental::types<T...> const&, F&& f) { 63 return static_cast<F&&>(f)(hana::type<T>{}...); 64 } 65 66 template <typename ...T, typename F, typename = typename std::enable_if< 67 hana::Metafunction<F>::value 68 >::type> 69 static constexpr hana::type<typename F::template apply<T...>::type> applyunpack_impl70 apply(hana::experimental::types<T...> const&, F const&) { return {}; } 71 }; 72 73 // Functor 74 template <> 75 struct transform_impl<hana::experimental::types_tag> { 76 template <typename ...T, typename F, typename = typename std::enable_if< 77 !hana::Metafunction<F>::value 78 >::type> applytransform_impl79 static constexpr auto apply(hana::experimental::types<T...> const&, F&& f) 80 -> hana::experimental::types<typename decltype(+f(hana::type<T>{}))::type...> 81 { return {}; } 82 83 template <typename ...T, typename F, typename = typename std::enable_if< 84 hana::Metafunction<F>::value 85 >::type> 86 static constexpr hana::experimental::types<typename F::template apply<T>::type...> applytransform_impl87 apply(hana::experimental::types<T...> const&, F const&) { return {}; } 88 }; 89 90 // Iterable 91 template <> 92 struct at_impl<hana::experimental::types_tag> { 93 template <typename ...T, typename N> 94 static constexpr auto applyat_impl95 apply(hana::experimental::types<T...> const&, N const&) { 96 using Nth = typename detail::type_at<N::value, T...>::type; 97 return hana::type<Nth>{}; 98 } 99 }; 100 101 template <> 102 struct is_empty_impl<hana::experimental::types_tag> { 103 template <typename ...T> 104 static constexpr hana::bool_<sizeof...(T) == 0> applyis_empty_impl105 apply(hana::experimental::types<T...> const&) 106 { return {}; } 107 }; 108 109 template <> 110 struct drop_front_impl<hana::experimental::types_tag> { 111 template <std::size_t n, typename ...T, std::size_t ...i> 112 static hana::experimental::types<typename detail::type_at<i + n, T...>::type...> 113 helper(std::index_sequence<i...>); 114 115 template <typename ...T, typename N> 116 static constexpr auto applydrop_front_impl117 apply(hana::experimental::types<T...> const&, N const&) { 118 constexpr std::size_t n = N::value > sizeof...(T) ? sizeof...(T) : N::value; 119 using Indices = std::make_index_sequence<sizeof...(T) - n>; 120 return decltype(helper<n, T...>(Indices{})){}; 121 } 122 }; 123 124 // Searchable 125 template <> 126 struct contains_impl<hana::experimental::types_tag> { 127 template <typename U> 128 struct is_same_as { 129 template <typename T> 130 struct apply { 131 static constexpr bool value = std::is_same<U, T>::value; 132 }; 133 }; 134 135 template <typename ...T, typename U> 136 static constexpr auto apply(hana::experimental::types<T...> const&, U const&) 137 -> hana::bool_< 138 detail::any_of<is_same_as<typename U::type>::template apply, T...>::value 139 > 140 { return {}; } 141 142 static constexpr hana::false_ apply(...) { return {}; } 143 }; 144 145 // Comparable 146 template <> 147 struct equal_impl<hana::experimental::types_tag, hana::experimental::types_tag> { 148 template <typename Types> 149 static constexpr hana::true_ apply(Types const&, Types const&) 150 { return {}; } 151 152 template <typename Ts, typename Us> 153 static constexpr hana::false_ apply(Ts const&, Us const&) 154 { return {}; } 155 }; 156 BOOST_HANA_NAMESPACE_END 157 158 #endif // !BOOST_HANA_EXPERIMENTAL_TYPES_HPP 159