3 Defines `boost::hana::type` and related utilities.
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)
10 #ifndef BOOST_HANA_TYPE_HPP
11 #define BOOST_HANA_TYPE_HPP
13 #include <boost/hana/fwd/type.hpp>
15 #include <boost/hana/bool.hpp>
16 #include <boost/hana/config.hpp>
17 #include <boost/hana/core/when.hpp>
18 #include <boost/hana/detail/operators/adl.hpp>
19 #include <boost/hana/detail/operators/comparable.hpp>
20 #include <boost/hana/fwd/concept/metafunction.hpp>
21 #include <boost/hana/fwd/core/make.hpp>
22 #include <boost/hana/fwd/equal.hpp>
23 #include <boost/hana/fwd/hash.hpp>
24 #include <boost/hana/integral_constant.hpp>
26 #include <type_traits>
30 namespace boost { namespace hana {
31 //////////////////////////////////////////////////////////////////////////
33 //////////////////////////////////////////////////////////////////////////
36 struct basic_type : detail::operators::adl<basic_type<T>> {
37 using hana_tag = type_tag;
40 constexpr auto operator+() const { return *this; }
44 //////////////////////////////////////////////////////////////////////////
46 //////////////////////////////////////////////////////////////////////////
49 struct _ : basic_type<T> { };
52 //////////////////////////////////////////////////////////////////////////
54 //////////////////////////////////////////////////////////////////////////
56 template <typename T, typename = type_tag>
58 using type = typename std::remove_reference<T>::type;
62 struct decltype_t<T, typename hana::tag_of<T>::type> {
63 using type = typename std::remove_reference<T>::type::type;
69 constexpr auto decltype_t::operator()(T&&) const
70 { return hana::type_c<typename detail::decltype_t<T>::type>; }
73 //////////////////////////////////////////////////////////////////////////
75 //////////////////////////////////////////////////////////////////////////
77 template <typename T, typename = type_tag>
79 using type = typename std::remove_cv<
80 typename std::remove_reference<T>::type
85 struct typeid_t<T, typename hana::tag_of<T>::type> {
86 using type = typename std::remove_reference<T>::type::type;
91 constexpr auto typeid_t::operator()(T&&) const
92 { return hana::type_c<typename detail::typeid_t<T>::type>; }
95 //////////////////////////////////////////////////////////////////////////
97 //////////////////////////////////////////////////////////////////////////
99 struct make_impl<type_tag> {
100 template <typename T>
101 static constexpr auto apply(T&& t)
102 { return hana::typeid_(static_cast<T&&>(t)); }
105 //////////////////////////////////////////////////////////////////////////
107 //////////////////////////////////////////////////////////////////////////
109 template <typename T>
110 constexpr auto sizeof_t::operator()(T&&) const
111 { return hana::size_c<sizeof(typename detail::decltype_t<T>::type)>; }
114 //////////////////////////////////////////////////////////////////////////
116 //////////////////////////////////////////////////////////////////////////
118 template <typename T>
119 constexpr auto alignof_t::operator()(T&&) const
120 { return hana::size_c<alignof(typename detail::decltype_t<T>::type)>; }
123 //////////////////////////////////////////////////////////////////////////
125 //////////////////////////////////////////////////////////////////////////
126 namespace type_detail {
127 template <typename F, typename ...Args, typename = decltype(
128 std::declval<F&&>()(std::declval<Args&&>()...)
130 constexpr auto is_valid_impl(int) { return hana::true_c; }
132 template <typename F, typename ...Args>
133 constexpr auto is_valid_impl(...) { return hana::false_c; }
135 template <typename F>
136 struct is_valid_fun {
137 template <typename ...Args>
138 constexpr auto operator()(Args&& ...) const
139 { return is_valid_impl<F, Args&&...>(int{}); }
144 template <typename F>
145 constexpr auto is_valid_t::operator()(F&&) const
146 { return type_detail::is_valid_fun<F&&>{}; }
148 template <typename F, typename ...Args>
149 constexpr auto is_valid_t::operator()(F&&, Args&& ...) const
150 { return type_detail::is_valid_impl<F&&, Args&&...>(int{}); }
153 //////////////////////////////////////////////////////////////////////////
155 //////////////////////////////////////////////////////////////////////////
156 // Note: We have to use the very complicated trick below instead of just
157 // mentionning `F<T...>` in a SFINAE-able context because of CWG 1430
158 // (http://www.open-std.org/Jtc1/sc22/wg21/docs/cwg_active.html#1430).
159 namespace template_detail {
160 template <typename ...T> struct args;
161 template <typename ...> using always_void = void;
163 template <template <typename ...> class F, typename Args, typename = void>
164 struct specialization_is_valid
168 template <template <typename ...> class F, typename ...T>
169 struct specialization_is_valid<F, args<T...>, always_void<F<T...>>>
172 } // end namespace detail
174 template <template <typename ...> class F>
176 template <typename ...T>
178 using type = F<T...>;
181 template <typename ...T, typename = std::enable_if_t<
182 template_detail::specialization_is_valid<F, template_detail::args<typename T::type...>>::value
184 constexpr auto operator()(T const& ...) const
185 { return hana::type<F<typename T::type...>>{}; }
188 //////////////////////////////////////////////////////////////////////////
190 //////////////////////////////////////////////////////////////////////////
191 template <template <typename ...> class F>
192 struct metafunction_t {
193 template <typename ...T>
194 using apply = F<T...>;
196 template <typename ...T>
197 constexpr hana::type<typename F<typename T::type...>::type>
198 operator()(T const& ...) const { return {}; }
201 //////////////////////////////////////////////////////////////////////////
202 // metafunction_class
203 //////////////////////////////////////////////////////////////////////////
205 template <typename F, typename ...T>
206 struct always_first { using type = F; };
208 template <typename F>
209 struct metafunction_class_t {
210 template <typename ...T>
211 using apply = typename detail::always_first<F, T...>::type::template apply<T...>;
213 template <typename ...T>
214 constexpr hana::type<typename detail::always_first<F, T...>::type::template apply<typename T::type...>::type>
215 operator()(T const& ...) const { return {}; }
218 //////////////////////////////////////////////////////////////////////////
220 //////////////////////////////////////////////////////////////////////////
221 template <template <typename ...> class F>
222 struct Metafunction<template_t<F>> {
223 static constexpr bool value = true;
226 template <template <typename ...> class F>
227 struct Metafunction<metafunction_t<F>> {
228 static constexpr bool value = true;
231 template <typename F>
232 struct Metafunction<metafunction_class_t<F>> {
233 static constexpr bool value = true;
236 //////////////////////////////////////////////////////////////////////////
238 //////////////////////////////////////////////////////////////////////////
239 template <typename F>
241 template <typename ...T, typename Result =
242 typename detail::always_first<F, T...>::type::template apply<typename T::type...>::type
244 constexpr Result operator()(T const& ...) const {
249 //////////////////////////////////////////////////////////////////////////
251 //////////////////////////////////////////////////////////////////////////
254 struct comparable_operators<type_tag> {
255 static constexpr bool value = true;
259 //////////////////////////////////////////////////////////////////////////
261 //////////////////////////////////////////////////////////////////////////
263 struct equal_impl<type_tag, type_tag> {
264 template <typename T, typename U>
265 static constexpr auto apply(basic_type<T> const&, basic_type<U> const&)
266 { return hana::false_c; }
268 template <typename T>
269 static constexpr auto apply(basic_type<T> const&, basic_type<T> const&)
270 { return hana::true_c; }
273 //////////////////////////////////////////////////////////////////////////
275 //////////////////////////////////////////////////////////////////////////
277 struct hash_impl<hana::type_tag> {
278 template <typename T>
279 static constexpr T apply(T const& t)
282 }} // end namespace boost::hana
284 #endif // !BOOST_HANA_TYPE_HPP