to.hpp 8.0 KB

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