/*============================================================================= Copyright (c) 2011-2017 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_GENERATOR_DETAIL_NEXT_GENERATOR_HPP #define SPROUT_GENERATOR_DETAIL_NEXT_GENERATOR_HPP #include #include #include #include #include #include #include #include #include #include #include namespace sprout_adl { sprout::not_found_via_adl get_next_generator(...); } // namespace sprout_adl namespace sprout { namespace detail { template struct has_mem_next_generator_test { public: template< typename U = T, typename = typename sprout::identity().next_generator())>::type > static sprout::true_type test(int); static sprout::false_type test(...); }; #if defined(_MSC_VER) && (_MSC_VER > 1900) template::test(0))>::type> struct has_mem_next_generator : public Base_ {}; #else template struct has_mem_next_generator : public sprout::identity::test(0))>::type {}; #endif template struct is_substitutable_const_next_generator : public sprout::bool_constant< sprout::detail::has_mem_next_generator::value > {}; template struct get_next_generator_impl; template struct get_next_generator_impl< Gen, typename std::enable_if< std::is_lvalue_reference::value && !std::is_const::type>::value && sprout::detail::is_substitutable_const_next_generator::value >::type > { public: static SPROUT_CONSTEXPR decltype(std::declval().next_generator()) get_next_generator(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(std::declval().next_generator()) { typedef decltype(std::declval().next_generator()) type; return sprout::const_reference_cast(sprout::as_const(gen).next_generator()); } }; template struct get_next_generator_impl< Gen, typename std::enable_if< std::is_lvalue_reference::value && !std::is_const::type>::value && !sprout::detail::is_substitutable_const_next_generator::value && sprout::detail::has_mem_next_generator::value >::type > { public: static SPROUT_CONSTEXPR decltype(std::declval().next_generator()) get_next_generator(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(std::declval().next_generator()) { return gen.next_generator(); } }; template struct get_next_generator_impl< Gen, typename std::enable_if< std::is_lvalue_reference::value && !std::is_const::type>::value && !sprout::detail::is_substitutable_const_next_generator::value && !sprout::detail::has_mem_next_generator::value && sprout::is_input_iterator::value >::type > { public: static SPROUT_CONSTEXPR decltype(std::declval()) get_next_generator(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(std::declval()) { return gen; } }; template struct get_next_generator_impl< Gen, typename std::enable_if< std::is_lvalue_reference::value && !std::is_const::type>::value && !sprout::detail::is_substitutable_const_next_generator::value && !sprout::detail::has_mem_next_generator::value && !sprout::is_input_iterator::value >::type > { public: static SPROUT_CONSTEXPR decltype(sprout::tuples::get<1>(std::declval())) get_next_generator(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(sprout::tuples::get<1>(std::declval())) { return sprout::tuples::get<1>(gen); } }; template struct get_next_generator_impl< Gen, typename std::enable_if< std::is_rvalue_reference::value && !std::is_const::type>::value && sprout::detail::is_substitutable_const_next_generator::value >::type > { public: static SPROUT_CONSTEXPR decltype(std::declval().next_generator()) get_next_generator(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(std::declval().next_generator()) { typedef decltype(std::declval().next_generator()) type; return sprout::const_reference_cast(sprout::as_const(sprout::move(gen)).next_generator()); } }; template struct get_next_generator_impl< Gen, typename std::enable_if< std::is_rvalue_reference::value && !std::is_const::type>::value && !sprout::detail::is_substitutable_const_next_generator::value && sprout::detail::has_mem_next_generator::value >::type > { public: static SPROUT_CONSTEXPR decltype(std::declval().next_generator()) get_next_generator(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(std::declval().next_generator()) { return sprout::move(gen).next_generator(); } }; template struct get_next_generator_impl< Gen, typename std::enable_if< std::is_rvalue_reference::value && !std::is_const::type>::value && !sprout::detail::is_substitutable_const_next_generator::value && !sprout::detail::has_mem_next_generator::value && sprout::is_input_iterator::value >::type > { public: static SPROUT_CONSTEXPR decltype(std::declval()) get_next_generator(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(std::declval()) { return sprout::move(gen); } }; template struct get_next_generator_impl< Gen, typename std::enable_if< std::is_rvalue_reference::value && !std::is_const::type>::value && !sprout::detail::is_substitutable_const_next_generator::value && !sprout::detail::has_mem_next_generator::value && !sprout::is_input_iterator::value >::type > { public: static SPROUT_CONSTEXPR decltype(sprout::tuples::get<1>(std::declval())) get_next_generator(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(sprout::tuples::get<1>(std::declval())) { return sprout::tuples::get<1>(sprout::move(gen)); } }; template struct get_next_generator_impl< Gen, typename std::enable_if< std::is_reference::value && std::is_const::type>::value && sprout::detail::has_mem_next_generator::value >::type > { public: static SPROUT_CONSTEXPR decltype(std::declval().next_generator()) get_next_generator(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(std::declval().next_generator()) { return gen.next_generator(); } }; template struct get_next_generator_impl< Gen, typename std::enable_if< std::is_reference::value && std::is_const::type>::value && !sprout::detail::has_mem_next_generator::value && sprout::is_input_iterator::value >::type > { public: static SPROUT_CONSTEXPR decltype(std::declval()) get_next_generator(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(std::declval()) { return gen; } }; template struct get_next_generator_impl< Gen, typename std::enable_if< std::is_reference::value && std::is_const::type>::value && !sprout::detail::has_mem_next_generator::value && !sprout::is_input_iterator::value >::type > { public: static SPROUT_CONSTEXPR decltype(sprout::tuples::get<1>(std::declval())) get_next_generator(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(sprout::tuples::get<1>(std::declval())) { return sprout::tuples::get<1>(gen); } }; } // namespace detail } // namespace sprout namespace sprout_generator_detail { template inline SPROUT_CONSTEXPR decltype(sprout::detail::get_next_generator_impl::get_next_generator(std::declval())) get_next_generator(Gen& gen) SPROUT_NOEXCEPT_IF_EXPR(sprout::detail::get_next_generator_impl::get_next_generator(std::declval())) { return sprout::detail::get_next_generator_impl::get_next_generator(gen); } template inline SPROUT_CONSTEXPR typename std::enable_if< !std::is_const::value && !std::is_volatile::value && !std::is_reference::value, decltype(sprout::detail::get_next_generator_impl::get_next_generator(std::declval())) >::type get_next_generator(Gen&& gen) SPROUT_NOEXCEPT_IF_EXPR(sprout::detail::get_next_generator_impl::get_next_generator(std::declval())) { return sprout::detail::get_next_generator_impl::get_next_generator(sprout::move(gen)); } template inline SPROUT_CONSTEXPR decltype(sprout::detail::get_next_generator_impl::get_next_generator(std::declval())) get_next_generator(Gen const& gen) SPROUT_NOEXCEPT_IF_EXPR(sprout::detail::get_next_generator_impl::get_next_generator(std::declval())) { return sprout::detail::get_next_generator_impl::get_next_generator(gen); } } // namespace sprout_generator_detail #endif // #ifndef SPROUT_GENERATOR_DETAIL_NEXT_GENERATOR_HPP