1/*!
2@file
3Defines `boost::hana::to` and related utilities.
4
5Copyright Louis Dionne 2013-2022
6Distributed 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
30namespace boost { namespace hana {
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 To, typename From, typename = void>
43 struct maybe_static_cast : no_conversion {
44 template <typename X>
45 static constexpr auto apply(X const&) {
46 static_assert(detail::wrong<to_impl<To, From>, X>{},
47 "no conversion is available between the provided types");
48 }
49 };
50
51 template <typename To, typename From>
52 struct maybe_static_cast<To, From, decltype((void)
53 static_cast<To>(std::declval<From>())
54 )> {
55 template <typename X>
56 static constexpr To apply(X&& x)
57 { return static_cast<To>(static_cast<X&&>(x)); }
58 };
59 } // end namespace convert_detail
60
61 template <typename To, typename From, bool condition>
62 struct to_impl<To, From, when<condition>>
63 : convert_detail::maybe_static_cast<To, From>
64 { };
65
66 template <typename To>
67 struct to_impl<To, To> : embedding<> {
68 template <typename X>
69 static constexpr X apply(X&& x)
70 { return static_cast<X&&>(x); }
71 };
72
73 //! @cond
74 template <typename To>
75 template <typename X>
76 constexpr decltype(auto) to_t<To>::operator()(X&& x) const {
77 using From = typename hana::tag_of<X>::type;
78 return to_impl<To, From>::apply(static_cast<X&&>(x));
79 }
80 //! @endcond
81
82#define BOOST_HANA_DEFINE_EMBEDDING_IMPL(TO, FROM) \
83 template <> \
84 struct to_impl<TO, FROM> : embedding<> \
85 { static constexpr TO apply(FROM x) { return x; } } \
86/**/
87 BOOST_HANA_DEFINE_EMBEDDING_IMPL(long double, double);
88 BOOST_HANA_DEFINE_EMBEDDING_IMPL(long double, float);
89 BOOST_HANA_DEFINE_EMBEDDING_IMPL(double , float);
90
91 BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed long);
92 BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed int);
93 BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed short);
94 BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed char);
95 BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long , signed int);
96 BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long , signed short);
97 BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long , signed char);
98 BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed int , signed short);
99 BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed int , signed char);
100 BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed short , signed char);
101
102 BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned long);
103 BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned int);
104 BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned short);
105 BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned char);
106 BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long , unsigned int);
107 BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long , unsigned short);
108 BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long , unsigned char);
109 BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned int , unsigned short);
110 BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned int , unsigned char);
111 BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned short , unsigned char);
112#undef BOOST_HANA_DEFINE_EMBEDDING_IMPL
113
114 namespace detail {
115 template <typename T>
116 struct copy_char_signedness {
117 using type = typename std::conditional<std::is_signed<char>::value,
118 std::make_signed<T>, std::make_unsigned<T>
119 >::type::type;
120 };
121 }
122
123 // If `char` is signed, we define an embedding from `char` to any signed
124 // integral type. Otherwise, we define one from `char` to any unsigned
125 // integral type.
126#define BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(TO) \
127 template <> \
128 struct to_impl<detail::copy_char_signedness<TO>::type, char> \
129 : embedding<> \
130 { \
131 static constexpr detail::copy_char_signedness<TO>::type \
132 apply(char x) \
133 { return x; } \
134 } \
135/**/
136 BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(long long);
137 BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(long);
138 BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(int);
139 BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(short);
140#undef BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL
141
142 template <typename T>
143 struct to_impl<T*, decltype(nullptr)> : embedding<> {
144 static constexpr T* apply(decltype(nullptr)) { return nullptr; }
145 };
146
147 //////////////////////////////////////////////////////////////////////////
148 // is_convertible
149 //////////////////////////////////////////////////////////////////////////
150 template <typename From, typename To, typename>
151 struct is_convertible : std::true_type { };
152
153 template <typename From, typename To>
154 struct is_convertible<From, To, decltype((void)
155 static_cast<convert_detail::no_conversion>(*(to_impl<To, From>*)0)
156 )> : std::false_type { };
157
158 //////////////////////////////////////////////////////////////////////////
159 // is_embedded
160 //////////////////////////////////////////////////////////////////////////
161 template <typename From, typename To, typename>
162 struct is_embedded : std::false_type { };
163
164 template <typename From, typename To>
165 struct is_embedded<From, To, decltype((void)
166 static_cast<embedding<true>>(*(to_impl<To, From>*)0)
167 )> : std::true_type { };
168
169 //////////////////////////////////////////////////////////////////////////
170 // Conversion for Constants
171 //////////////////////////////////////////////////////////////////////////
172 template <typename To, typename From>
173 struct to_impl<To, From, when<
174 hana::Constant<From>::value &&
175 is_convertible<typename From::value_type, To>::value
176 >> : embedding<is_embedded<typename From::value_type, To>::value> {
177 template <typename X>
178 static constexpr decltype(auto) apply(X const&)
179 { return hana::to<To>(hana::value<X>()); }
180 };
181
182 //////////////////////////////////////////////////////////////////////////
183 // Foldable -> Sequence
184 //////////////////////////////////////////////////////////////////////////
185 template <typename S, typename F>
186 struct to_impl<S, F, when<
187 hana::Sequence<S>::value &&
188 hana::Foldable<F>::value
189 >> : embedding<Sequence<F>::value> {
190 template <typename Xs>
191 static constexpr decltype(auto) apply(Xs&& xs)
192 { return hana::unpack(static_cast<Xs&&>(xs), hana::make<S>); }
193 };
194}} // end namespace boost::hana
195
196#endif // !BOOST_HANA_CORE_TO_HPP
197

source code of boost/libs/hana/include/boost/hana/core/to.hpp