/*============================================================================= Copyright (c) 2011-2019 Bolero MURAKAMI https://github.com/bolero-MURAKAMI/Sprout Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #ifndef SPROUT_ITERATOR_CONST_REFERENCE_CAST_HPP #define SPROUT_ITERATOR_CONST_REFERENCE_CAST_HPP #include #include #include #include #include #include #include #include namespace sprout { // // is_const_reference_cast_convertible // template struct is_const_reference_cast_convertible : public sprout::bool_constant< sprout::is_const_cast_convertible::value || std::is_same::type, typename std::remove_cv::type>::value > {}; template struct is_const_reference_cast_convertible : public sprout::is_const_reference_cast_convertible {}; template struct is_const_reference_cast_convertible : public sprout::is_const_reference_cast_convertible {}; template struct is_const_reference_cast_convertible : public sprout::is_const_reference_cast_convertible {}; template struct is_const_reference_cast_convertible : public sprout::is_const_reference_cast_convertible {}; template struct is_const_reference_cast_convertible : public sprout::is_const_reference_cast_convertible {}; template struct is_const_reference_cast_convertible : public sprout::is_const_reference_cast_convertible {}; template struct is_const_reference_cast_convertible : public sprout::is_const_reference_cast_convertible {}; template struct is_const_reference_cast_convertible : public sprout::is_const_reference_cast_convertible {}; template struct is_const_reference_cast_convertible : public sprout::is_const_reference_cast_convertible {}; template struct is_const_reference_cast_convertible : public sprout::is_const_reference_cast_convertible {}; template struct is_const_reference_cast_convertible : public sprout::is_const_reference_cast_convertible {}; template struct is_const_reference_cast_convertible : public sprout::is_const_reference_cast_convertible {}; template struct is_const_reference_cast_convertible : public sprout::is_const_reference_cast_convertible {}; template struct is_const_reference_cast_convertible : public sprout::is_const_reference_cast_convertible {}; template struct is_const_reference_cast_convertible : public sprout::is_const_reference_cast_convertible {}; } // namespace sprout namespace sprout_adl { template sprout::not_found_via_adl const_reference_conversion(...); } // namespace sprout_adl namespace sprout { namespace iterator_detail { template< typename T, typename U, typename sprout::enabler_if< sprout::is_const_reference_cast_convertible::value && std::is_reference::value >::type = sprout::enabler > inline SPROUT_CONSTEXPR T const_reference_conversion(U& t) { return const_cast(t); } template< typename T, typename U, typename sprout::enabler_if< sprout::is_const_reference_cast_convertible::value && std::is_reference::value >::type = sprout::enabler > inline SPROUT_CONSTEXPR T const_reference_conversion(U const& t) { return const_cast(t); } template< typename T, typename U, typename sprout::enabler_if< sprout::is_const_reference_cast_convertible::value && std::is_pointer::value >::type = sprout::enabler > inline SPROUT_CONSTEXPR T const_reference_conversion(U& t) { return const_cast(t); } template< typename T, typename U, typename sprout::enabler_if< sprout::is_const_reference_cast_convertible::value && std::is_pointer::value >::type = sprout::enabler > inline SPROUT_CONSTEXPR T const_reference_conversion(U const& t) { return const_cast(t); } template< typename T, typename U, typename sprout::enabler_if< sprout::is_const_reference_cast_convertible::value && !std::is_reference::value && !std::is_pointer::value >::type = sprout::enabler > inline SPROUT_CONSTEXPR T const_reference_conversion(U& t) { return static_cast(t); } template< typename T, typename U, typename sprout::enabler_if< sprout::is_const_reference_cast_convertible::value && !std::is_reference::value && !std::is_pointer::value >::type = sprout::enabler > inline SPROUT_CONSTEXPR T const_reference_conversion(U const& t) { return static_cast(t); } } // namespace iterator_detail } // namespace sprout namespace sprout_iterator_detail { template inline SPROUT_CONSTEXPR To call_const_reference_conversion(From&& t) { using sprout::iterator_detail::const_reference_conversion; using sprout_adl::const_reference_conversion; return const_reference_conversion(SPROUT_FORWARD(From, t)); } } // namespace sprout_iterator_detail namespace sprout { // // const_reference_cast // template inline SPROUT_CONSTEXPR To const_reference_cast(From&& t) { return sprout_iterator_detail::call_const_reference_conversion(SPROUT_FORWARD(From, t)); } } // namespace sprout // // note: // const_reference_cast is an adaptable function for interconversion // with reference and const_reference. // If you want to adapt a user-defined reference proxy class to const_reference_cast: // - Specialize sprout::is_const_reference_cast_convertible. // - Overload const_reference_conversion as to be lookup in the ADL. // // example: // #include // #include // #include // #include // /* Mylib::Reference is an user-defined reference proxy class*/ // namespace Mylib { // template // struct Reference { // T* p; // typedef T* pointer; // /* definition reference proxy interface... */ // }; // } // /* const_reference_cast adapt for Mylib::Reference */ // namespace sprout { // template // struct is_const_reference_cast_convertible< // Mylib::Reference, // Mylib::Reference // > // : public sprout::is_same< // typename std::remove_cv::type, // typename std::remove_cv::type // > // {}; // } // namespace Mylib { // template // inline SPROUT_CONSTEXPR typename std::enable_if< // sprout::is_const_reference_cast_convertible, To>::value, // To // >::type // const_reference_conversion(Reference const& it) { // return To{const_cast(it.p)}; // } // } // /* test const_reference_cast with Mylib::Reference */ // constexpr Mylib::Reference it{0}; // static_assert(sprout::const_reference_cast >(it).p == 0, ""); // #endif // #ifndef SPROUT_ITERATOR_CONST_REFERENCE_CAST_HPP