/*! @file Defines `boost::hana::to` and related utilities. @copyright Louis Dionne 2013-2017 Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) */ #ifndef BOOST_HANA_CORE_TO_HPP #define BOOST_HANA_CORE_TO_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include BOOST_HANA_NAMESPACE_BEGIN ////////////////////////////////////////////////////////////////////////// // to ////////////////////////////////////////////////////////////////////////// //! @cond template struct to_impl : to_impl> { }; //! @endcond namespace convert_detail { struct no_conversion { }; template struct maybe_static_cast : no_conversion { template static constexpr auto apply(X const&) { static_assert(detail::wrong, X>{}, "no conversion is available between the provided types"); } }; template struct maybe_static_cast(std::declval()) )> { template static constexpr To apply(X&& x) { return static_cast(static_cast(x)); } }; } // end namespace convert_detail template struct to_impl> : convert_detail::maybe_static_cast { }; template struct to_impl : embedding<> { template static constexpr X apply(X&& x) { return static_cast(x); } }; //! @cond template template constexpr decltype(auto) to_t::operator()(X&& x) const { using From = typename hana::tag_of::type; return to_impl::apply(static_cast(x)); } //! @endcond #define BOOST_HANA_DEFINE_EMBEDDING_IMPL(TO, FROM) \ template <> \ struct to_impl : embedding<> \ { static constexpr TO apply(FROM x) { return x; } } \ /**/ BOOST_HANA_DEFINE_EMBEDDING_IMPL(long double, double); BOOST_HANA_DEFINE_EMBEDDING_IMPL(long double, float); BOOST_HANA_DEFINE_EMBEDDING_IMPL(double , float); BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed long); BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed int); BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed short); BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed char); BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long , signed int); BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long , signed short); BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long , signed char); BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed int , signed short); BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed int , signed char); BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed short , signed char); BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned long); BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned int); BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned short); BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned char); BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long , unsigned int); BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long , unsigned short); BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long , unsigned char); BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned int , unsigned short); BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned int , unsigned char); BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned short , unsigned char); #undef BOOST_HANA_DEFINE_EMBEDDING_IMPL namespace detail { template struct copy_char_signedness { using type = typename std::conditional::value, std::make_signed, std::make_unsigned >::type::type; }; } // If `char` is signed, we define an embedding from `char` to any signed // integral type. Otherwise, we define one from `char` to any unsigned // integral type. #define BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(TO) \ template <> \ struct to_impl::type, char> \ : embedding<> \ { \ static constexpr detail::copy_char_signedness::type \ apply(char x) \ { return x; } \ } \ /**/ BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(long long); BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(long); BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(int); BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(short); #undef BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL template struct to_impl : embedding<> { static constexpr T* apply(decltype(nullptr)) { return nullptr; } }; ////////////////////////////////////////////////////////////////////////// // is_convertible ////////////////////////////////////////////////////////////////////////// template struct is_convertible : std::true_type { }; template struct is_convertible(*(to_impl*)0) )> : std::false_type { }; ////////////////////////////////////////////////////////////////////////// // is_embedded ////////////////////////////////////////////////////////////////////////// template struct is_embedded : std::false_type { }; template struct is_embedded>(*(to_impl*)0) )> : std::true_type { }; ////////////////////////////////////////////////////////////////////////// // Conversion for Constants ////////////////////////////////////////////////////////////////////////// template struct to_impl::value && is_convertible::value >> : embedding::value> { template static constexpr decltype(auto) apply(X const&) { return hana::to(hana::value()); } }; ////////////////////////////////////////////////////////////////////////// // Foldable -> Sequence ////////////////////////////////////////////////////////////////////////// template struct to_impl::value && hana::Foldable::value >> : embedding::value> { template static constexpr decltype(auto) apply(Xs&& xs) { return hana::unpack(static_cast(xs), hana::make); } }; BOOST_HANA_NAMESPACE_END #endif // !BOOST_HANA_CORE_TO_HPP