1 /*! 2 @file 3 Defines `boost::hana::to` and related utilities. 4 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) 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 To, typename From, typename = void> 43 struct maybe_static_cast : no_conversion { 44 template <typename X> applyconvert_detail::maybe_static_cast45 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> applyconvert_detail::maybe_static_cast56 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> applyto_impl69 static constexpr X apply(X&& x) 70 { return static_cast<X&&>(x); } 71 }; 72 73 //! @cond 74 template <typename To> 75 template <typename X> operator ()(X && x) const76 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<> { applyto_impl144 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> applyto_impl178 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> applyto_impl191 static constexpr decltype(auto) apply(Xs&& xs) 192 { return hana::unpack(static_cast<Xs&&>(xs), hana::make<S>); } 193 }; 194 BOOST_HANA_NAMESPACE_END 195 196 #endif // !BOOST_HANA_CORE_TO_HPP 197