]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*! |
2 | @file | |
3 | Defines `boost::hana::type` and related utilities. | |
4 | ||
5 | @copyright Louis Dionne 2013-2016 | |
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_TYPE_HPP | |
11 | #define BOOST_HANA_TYPE_HPP | |
12 | ||
13 | #include <boost/hana/fwd/type.hpp> | |
14 | ||
15 | #include <boost/hana/bool.hpp> | |
16 | #include <boost/hana/config.hpp> | |
17 | #include <boost/hana/detail/operators/adl.hpp> | |
18 | #include <boost/hana/detail/operators/comparable.hpp> | |
19 | #include <boost/hana/fwd/concept/metafunction.hpp> | |
20 | #include <boost/hana/fwd/core/make.hpp> | |
21 | #include <boost/hana/fwd/equal.hpp> | |
22 | #include <boost/hana/fwd/hash.hpp> | |
23 | #include <boost/hana/integral_constant.hpp> | |
24 | ||
25 | #include <type_traits> | |
26 | #include <utility> | |
27 | ||
28 | ||
29 | BOOST_HANA_NAMESPACE_BEGIN | |
30 | ////////////////////////////////////////////////////////////////////////// | |
31 | // basic_type | |
32 | ////////////////////////////////////////////////////////////////////////// | |
33 | //! @cond | |
34 | template <typename T> | |
35 | struct basic_type : detail::operators::adl<basic_type<T>> { | |
36 | using hana_tag = type_tag; | |
37 | ||
38 | using type = T; | |
39 | constexpr auto operator+() const { return *this; } | |
40 | }; | |
41 | //! @endcond | |
42 | ||
43 | ////////////////////////////////////////////////////////////////////////// | |
44 | // type | |
45 | ////////////////////////////////////////////////////////////////////////// | |
46 | template <typename T> | |
47 | struct type_impl { | |
48 | struct _ : basic_type<T> { }; | |
49 | }; | |
50 | ||
51 | ////////////////////////////////////////////////////////////////////////// | |
52 | // decltype_ | |
53 | ////////////////////////////////////////////////////////////////////////// | |
54 | namespace detail { | |
55 | template <typename T, typename = type_tag> | |
56 | struct decltype_t { | |
57 | using type = typename std::remove_reference<T>::type; | |
58 | }; | |
59 | ||
60 | template <typename T> | |
61 | struct decltype_t<T, typename hana::tag_of<T>::type> { | |
62 | using type = typename std::remove_reference<T>::type::type; | |
63 | }; | |
64 | } | |
65 | ||
66 | //! @cond | |
67 | template <typename T> | |
68 | constexpr auto decltype_t::operator()(T&&) const | |
69 | { return hana::type_c<typename detail::decltype_t<T>::type>; } | |
70 | //! @endcond | |
71 | ||
72 | ////////////////////////////////////////////////////////////////////////// | |
73 | // typeid_ | |
74 | ////////////////////////////////////////////////////////////////////////// | |
75 | namespace detail { | |
76 | template <typename T, typename = type_tag> | |
77 | struct typeid_t { | |
78 | using type = typename std::remove_cv< | |
79 | typename std::remove_reference<T>::type | |
80 | >::type; | |
81 | }; | |
82 | ||
83 | template <typename T> | |
84 | struct typeid_t<T, typename hana::tag_of<T>::type> { | |
85 | using type = typename std::remove_reference<T>::type::type; | |
86 | }; | |
87 | } | |
88 | //! @cond | |
89 | template <typename T> | |
90 | constexpr auto typeid_t::operator()(T&&) const | |
91 | { return hana::type_c<typename detail::typeid_t<T>::type>; } | |
92 | //! @endcond | |
93 | ||
94 | ////////////////////////////////////////////////////////////////////////// | |
95 | // make<type_tag> | |
96 | ////////////////////////////////////////////////////////////////////////// | |
97 | template <> | |
98 | struct make_impl<type_tag> { | |
99 | template <typename T> | |
100 | static constexpr auto apply(T&& t) | |
101 | { return hana::typeid_(static_cast<T&&>(t)); } | |
102 | }; | |
103 | ||
104 | ////////////////////////////////////////////////////////////////////////// | |
105 | // sizeof_ | |
106 | ////////////////////////////////////////////////////////////////////////// | |
107 | //! @cond | |
108 | template <typename T> | |
109 | constexpr auto sizeof_t::operator()(T&&) const | |
110 | { return hana::size_c<sizeof(typename detail::decltype_t<T>::type)>; } | |
111 | //! @endcond | |
112 | ||
113 | ////////////////////////////////////////////////////////////////////////// | |
114 | // alignof_ | |
115 | ////////////////////////////////////////////////////////////////////////// | |
116 | //! @cond | |
117 | template <typename T> | |
118 | constexpr auto alignof_t::operator()(T&&) const | |
119 | { return hana::size_c<alignof(typename detail::decltype_t<T>::type)>; } | |
120 | //! @endcond | |
121 | ||
122 | ////////////////////////////////////////////////////////////////////////// | |
123 | // is_valid | |
124 | ////////////////////////////////////////////////////////////////////////// | |
125 | namespace type_detail { | |
126 | template <typename F, typename ...Args, typename = decltype( | |
127 | std::declval<F&&>()(std::declval<Args&&>()...) | |
128 | )> | |
129 | constexpr auto is_valid_impl(int) { return hana::true_c; } | |
130 | ||
131 | template <typename F, typename ...Args> | |
132 | constexpr auto is_valid_impl(...) { return hana::false_c; } | |
133 | ||
134 | template <typename F> | |
135 | struct is_valid_fun { | |
136 | template <typename ...Args> | |
137 | constexpr auto operator()(Args&& ...) const | |
138 | { return is_valid_impl<F, Args&&...>(int{}); } | |
139 | }; | |
140 | } | |
141 | ||
142 | //! @cond | |
143 | template <typename F> | |
144 | constexpr auto is_valid_t::operator()(F&&) const | |
145 | { return type_detail::is_valid_fun<F&&>{}; } | |
146 | ||
147 | template <typename F, typename ...Args> | |
148 | constexpr auto is_valid_t::operator()(F&&, Args&& ...) const | |
149 | { return type_detail::is_valid_impl<F&&, Args&&...>(int{}); } | |
150 | //! @endcond | |
151 | ||
152 | ////////////////////////////////////////////////////////////////////////// | |
153 | // template_ | |
154 | ////////////////////////////////////////////////////////////////////////// | |
155 | template <template <typename ...> class F> | |
156 | struct template_t { | |
157 | template <typename ...T> | |
158 | struct apply { | |
159 | using type = F<T...>; | |
160 | }; | |
161 | ||
162 | template <typename ...T> | |
163 | constexpr auto operator()(T const& ...) const | |
164 | { return hana::type<F<typename T::type...>>{}; } | |
165 | }; | |
166 | ||
167 | ////////////////////////////////////////////////////////////////////////// | |
168 | // metafunction | |
169 | ////////////////////////////////////////////////////////////////////////// | |
170 | template <template <typename ...> class F> | |
171 | struct metafunction_t { | |
172 | template <typename ...T> | |
173 | using apply = F<T...>; | |
174 | ||
175 | template <typename ...T> | |
176 | constexpr hana::type<typename F<typename T::type...>::type> | |
177 | operator()(T const& ...) const { return {}; } | |
178 | }; | |
179 | ||
180 | ////////////////////////////////////////////////////////////////////////// | |
181 | // Metafunction | |
182 | ////////////////////////////////////////////////////////////////////////// | |
183 | template <template <typename ...> class F> | |
184 | struct Metafunction<template_t<F>> { | |
185 | static constexpr bool value = true; | |
186 | }; | |
187 | ||
188 | template <template <typename ...> class F> | |
189 | struct Metafunction<metafunction_t<F>> { | |
190 | static constexpr bool value = true; | |
191 | }; | |
192 | ||
193 | template <typename F> | |
194 | struct Metafunction<metafunction_class_t<F>> { | |
195 | static constexpr bool value = true; | |
196 | }; | |
197 | ||
198 | ////////////////////////////////////////////////////////////////////////// | |
199 | // integral | |
200 | ////////////////////////////////////////////////////////////////////////// | |
201 | template <typename F> | |
202 | struct integral_t { | |
203 | template <typename ...T> | |
204 | constexpr auto operator()(T const& ...) const { | |
205 | using Result = typename F::template apply<typename T::type...>::type; | |
206 | return Result{}; | |
207 | } | |
208 | }; | |
209 | ||
210 | ////////////////////////////////////////////////////////////////////////// | |
211 | // Operators | |
212 | ////////////////////////////////////////////////////////////////////////// | |
213 | namespace detail { | |
214 | template <> | |
215 | struct comparable_operators<type_tag> { | |
216 | static constexpr bool value = true; | |
217 | }; | |
218 | } | |
219 | ||
220 | ////////////////////////////////////////////////////////////////////////// | |
221 | // Comparable | |
222 | ////////////////////////////////////////////////////////////////////////// | |
223 | template <> | |
224 | struct equal_impl<type_tag, type_tag> { | |
225 | template <typename T, typename U> | |
226 | static constexpr auto apply(basic_type<T> const&, basic_type<U> const&) | |
227 | { return hana::false_c; } | |
228 | ||
229 | template <typename T> | |
230 | static constexpr auto apply(basic_type<T> const&, basic_type<T> const&) | |
231 | { return hana::true_c; } | |
232 | }; | |
233 | ||
234 | ////////////////////////////////////////////////////////////////////////// | |
235 | // Hashable | |
236 | ////////////////////////////////////////////////////////////////////////// | |
237 | template <> | |
238 | struct hash_impl<hana::type_tag> { | |
239 | template <typename T> | |
240 | static constexpr T apply(T const& t) | |
241 | { return t; } | |
242 | }; | |
243 | BOOST_HANA_NAMESPACE_END | |
244 | ||
245 | #endif // !BOOST_HANA_TYPE_HPP |