]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*! |
2 | @file | |
3 | Defines `boost::hana::to` 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_CORE_TO_HPP | |
11 | #define BOOST_HANA_CORE_TO_HPP | |
12 | ||
13 | #include <boost/hana/fwd/core/to.hpp> | |
14 | ||
15 | #include <boost/hana/concept/constant.hpp> | |
16 | #include <boost/hana/concept/foldable.hpp> | |
17 | #include <boost/hana/concept/sequence.hpp> | |
18 | #include <boost/hana/config.hpp> | |
19 | #include <boost/hana/core/common.hpp> | |
20 | #include <boost/hana/core/dispatch.hpp> | |
21 | #include <boost/hana/core/make.hpp> | |
22 | #include <boost/hana/detail/wrong.hpp> | |
23 | #include <boost/hana/unpack.hpp> | |
24 | #include <boost/hana/value.hpp> | |
25 | ||
26 | #include <type_traits> | |
27 | #include <utility> | |
28 | ||
29 | ||
30 | BOOST_HANA_NAMESPACE_BEGIN | |
31 | ////////////////////////////////////////////////////////////////////////// | |
32 | // to | |
33 | ////////////////////////////////////////////////////////////////////////// | |
34 | //! @cond | |
35 | template <typename To, typename From, typename> | |
36 | struct to_impl : to_impl<To, From, when<true>> { }; | |
37 | //! @endcond | |
38 | ||
39 | namespace convert_detail { | |
40 | struct no_conversion { }; | |
41 | ||
42 | template <typename ...> | |
43 | struct is_valid { static constexpr bool value = true; }; | |
44 | } | |
45 | ||
46 | template <typename To, typename From, bool condition> | |
47 | struct to_impl<To, From, when<condition>> : convert_detail::no_conversion { | |
48 | template <typename X> | |
49 | static constexpr auto apply(X const&) { | |
50 | static_assert(detail::wrong<to_impl<To, From>, X>{}, | |
51 | "no conversion is available between the provided types"); | |
52 | } | |
53 | }; | |
54 | ||
55 | template <typename To, typename From> | |
56 | struct to_impl<To, From, when<convert_detail::is_valid< | |
57 | decltype(static_cast<To>(std::declval<From>())) | |
58 | >::value>> { | |
59 | template <typename X> | |
60 | static constexpr To apply(X&& x) | |
61 | { return static_cast<To>(static_cast<X&&>(x)); } | |
62 | }; | |
63 | ||
64 | template <typename To> | |
65 | struct to_impl<To, To> : embedding<> { | |
66 | template <typename X> | |
67 | static constexpr X apply(X&& x) | |
68 | { return static_cast<X&&>(x); } | |
69 | }; | |
70 | ||
71 | //! @cond | |
72 | template <typename To> | |
73 | template <typename X> | |
74 | constexpr decltype(auto) to_t<To>::operator()(X&& x) const { | |
75 | using From = typename hana::tag_of<X>::type; | |
76 | return to_impl<To, From>::apply(static_cast<X&&>(x)); | |
77 | } | |
78 | //! @endcond | |
79 | ||
80 | #define BOOST_HANA_DEFINE_EMBEDDING_IMPL(TO, FROM) \ | |
81 | template <> \ | |
82 | struct to_impl<TO, FROM> : embedding<> \ | |
83 | { static constexpr TO apply(FROM x) { return x; } } \ | |
84 | /**/ | |
85 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(long double, double); | |
86 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(long double, float); | |
87 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(double , float); | |
88 | ||
89 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed long); | |
90 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed int); | |
91 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed short); | |
92 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed char); | |
93 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long , signed int); | |
94 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long , signed short); | |
95 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long , signed char); | |
96 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed int , signed short); | |
97 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed int , signed char); | |
98 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed short , signed char); | |
99 | ||
100 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned long); | |
101 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned int); | |
102 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned short); | |
103 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned char); | |
104 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long , unsigned int); | |
105 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long , unsigned short); | |
106 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long , unsigned char); | |
107 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned int , unsigned short); | |
108 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned int , unsigned char); | |
109 | BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned short , unsigned char); | |
110 | #undef BOOST_HANA_DEFINE_EMBEDDING_IMPL | |
111 | ||
112 | namespace detail { | |
113 | template <typename T> | |
114 | struct copy_char_signedness { | |
115 | using type = typename std::conditional<std::is_signed<char>::value, | |
116 | std::make_signed<T>, std::make_unsigned<T> | |
117 | >::type::type; | |
118 | }; | |
119 | } | |
120 | ||
121 | // If `char` is signed, we define an embedding from `char` to any signed | |
122 | // integral type. Otherwise, we define one from `char` to any unsigned | |
123 | // integral type. | |
124 | #define BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(TO) \ | |
125 | template <> \ | |
126 | struct to_impl<detail::copy_char_signedness<TO>::type, char> \ | |
127 | : embedding<> \ | |
128 | { \ | |
129 | static constexpr detail::copy_char_signedness<TO>::type \ | |
130 | apply(char x) \ | |
131 | { return x; } \ | |
132 | } \ | |
133 | /**/ | |
134 | BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(long long); | |
135 | BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(long); | |
136 | BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(int); | |
137 | BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(short); | |
138 | #undef BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL | |
139 | ||
140 | template <typename T> | |
141 | struct to_impl<T*, decltype(nullptr)> : embedding<> { | |
142 | static constexpr T* apply(decltype(nullptr)) { return nullptr; } | |
143 | }; | |
144 | ||
145 | ////////////////////////////////////////////////////////////////////////// | |
146 | // is_convertible | |
147 | ////////////////////////////////////////////////////////////////////////// | |
148 | template <typename From, typename To, typename> | |
149 | struct is_convertible : std::true_type { }; | |
150 | ||
151 | template <typename From, typename To> | |
152 | struct is_convertible<From, To, decltype((void) | |
153 | static_cast<convert_detail::no_conversion>(*(to_impl<To, From>*)0) | |
154 | )> : std::false_type { }; | |
155 | ||
156 | ////////////////////////////////////////////////////////////////////////// | |
157 | // is_embedded | |
158 | ////////////////////////////////////////////////////////////////////////// | |
159 | template <typename From, typename To, typename> | |
160 | struct is_embedded : std::false_type { }; | |
161 | ||
162 | template <typename From, typename To> | |
163 | struct is_embedded<From, To, decltype((void) | |
164 | static_cast<embedding<true>>(*(to_impl<To, From>*)0) | |
165 | )> : std::true_type { }; | |
166 | ||
167 | ////////////////////////////////////////////////////////////////////////// | |
168 | // Conversion for Constants | |
169 | ////////////////////////////////////////////////////////////////////////// | |
170 | template <typename To, typename From> | |
171 | struct to_impl<To, From, when< | |
172 | hana::Constant<From>::value && | |
173 | is_convertible<typename From::value_type, To>::value | |
174 | >> : embedding<is_embedded<typename From::value_type, To>::value> { | |
175 | template <typename X> | |
176 | static constexpr decltype(auto) apply(X const&) | |
177 | { return hana::to<To>(hana::value<X>()); } | |
178 | }; | |
179 | ||
180 | ////////////////////////////////////////////////////////////////////////// | |
181 | // Foldable -> Sequence | |
182 | ////////////////////////////////////////////////////////////////////////// | |
183 | template <typename S, typename F> | |
184 | struct to_impl<S, F, when< | |
185 | hana::Sequence<S>::value && | |
186 | hana::Foldable<F>::value | |
187 | >> : embedding<Sequence<F>::value> { | |
188 | template <typename Xs> | |
189 | static constexpr decltype(auto) apply(Xs&& xs) | |
190 | { return hana::unpack(static_cast<Xs&&>(xs), hana::make<S>); } | |
191 | }; | |
192 | BOOST_HANA_NAMESPACE_END | |
193 | ||
194 | #endif // !BOOST_HANA_CORE_TO_HPP |