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> applyto_impl49 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> applyto_impl60 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> applyto_impl67 static constexpr X apply(X&& x) 68 { return static_cast<X&&>(x); } 69 }; 70 71 //! @cond 72 template <typename To> 73 template <typename X> operator ()(X && x) const74 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<> { applyto_impl142 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> applyto_impl176 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> applyto_impl189 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 195