/*============================================================================= 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_VALUE_HPP #define SPROUT_GENERATOR_DETAIL_NEXT_VALUE_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include namespace sprout_adl { sprout::not_found_via_adl generate_next_value(...); } // namespace sprout_adl namespace sprout { namespace detail { template struct has_mem_next_value_test { public: template< typename U = T, typename = typename sprout::identity().next_value())>::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_value : public Base_ {}; #else template struct has_mem_next_value : public sprout::identity::test(0))>::type {}; #endif template struct has_function_call_test { public: template< typename U = T, typename = typename sprout::identity()())>::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_function_call : public Base_ {}; #else template struct has_function_call : public sprout::identity::test(0))>::type {}; #endif template struct generate_next_value_impl; template struct generate_next_value_impl< Gen, typename std::enable_if< std::is_lvalue_reference::value && !std::is_const::type>::value && sprout::detail::has_mem_next_value::value >::type > { public: static SPROUT_CONSTEXPR decltype(std::declval().next_value()) generate_next_value(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(std::declval().next_value()) { return gen.next_value(); } }; template struct generate_next_value_impl< Gen, typename std::enable_if< std::is_lvalue_reference::value && !std::is_const::type>::value && !sprout::detail::has_mem_next_value::value && sprout::is_input_iterator::value >::type > { public: static SPROUT_CONSTEXPR decltype(sprout::next(std::declval())) generate_next_value(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(sprout::next(std::declval())) { return sprout::next(gen); } }; template struct generate_next_value_impl< Gen, typename std::enable_if< std::is_lvalue_reference::value && !std::is_const::type>::value && !sprout::detail::has_mem_next_value::value && !sprout::is_input_iterator::value && sprout::detail::has_function_call::value >::type > { public: static SPROUT_CONSTEXPR decltype(std::declval()()) generate_next_value(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(std::declval()()) { return gen(); } }; template struct generate_next_value_impl< Gen, typename std::enable_if< std::is_lvalue_reference::value && !std::is_const::type>::value && !sprout::detail::has_mem_next_value::value && !sprout::is_input_iterator::value && !sprout::detail::has_function_call::value >::type > { public: static SPROUT_CONSTEXPR decltype(sprout::generators::next_value(sprout::generators::next_generator(std::declval()))) generate_next_value(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(sprout::generators::next_value(sprout::generators::next_generator(std::declval()))) { return sprout::generators::next_value(sprout::generators::next_generator(gen)); } }; template struct generate_next_value_impl< Gen, typename std::enable_if< std::is_rvalue_reference::value && !std::is_const::type>::value && sprout::detail::has_mem_next_value::value >::type > { public: static SPROUT_CONSTEXPR decltype(std::declval().next_value()) generate_next_value(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(std::declval().next_value()) { return sprout::move(gen).next_value(); } }; template struct generate_next_value_impl< Gen, typename std::enable_if< std::is_rvalue_reference::value && !std::is_const::type>::value && !sprout::detail::has_mem_next_value::value && sprout::is_input_iterator::value >::type > { public: static SPROUT_CONSTEXPR decltype(sprout::next(std::declval())) generate_next_value(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(sprout::next(std::declval())) { return sprout::next(sprout::move(gen)); } }; template struct generate_next_value_impl< Gen, typename std::enable_if< std::is_rvalue_reference::value && !std::is_const::type>::value && !sprout::detail::has_mem_next_value::value && !sprout::is_input_iterator::value && sprout::detail::has_function_call::value >::type > { public: static SPROUT_CONSTEXPR decltype(std::declval()()) generate_next_value(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(std::declval()()) { return sprout::move(gen)(); } }; template struct generate_next_value_impl< Gen, typename std::enable_if< std::is_rvalue_reference::value && !std::is_const::type>::value && !sprout::detail::has_mem_next_value::value && !sprout::is_input_iterator::value && !sprout::detail::has_function_call::value >::type > { public: static SPROUT_CONSTEXPR decltype(sprout::generators::next_value(sprout::generators::next_generator(std::declval()))) generate_next_value(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(sprout::generators::next_value(sprout::generators::next_generator(std::declval()))) { return sprout::generators::next_value(sprout::generators::next_generator(sprout::move(gen))); } }; template struct generate_next_value_impl< Gen, typename std::enable_if< std::is_reference::value && std::is_const::type>::value && sprout::detail::has_mem_next_value::value >::type > { public: static SPROUT_CONSTEXPR decltype(std::declval().next_value()) generate_next_value(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(std::declval().next_value()) { return gen.next_value(); } }; template struct generate_next_value_impl< Gen, typename std::enable_if< std::is_reference::value && std::is_const::type>::value && !sprout::detail::has_mem_next_value::value && sprout::is_input_iterator::value >::type > { public: static SPROUT_CONSTEXPR decltype(sprout::next(std::declval())) generate_next_value(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(sprout::next(std::declval())) { return sprout::next(gen); } }; template struct generate_next_value_impl< Gen, typename std::enable_if< std::is_reference::value && std::is_const::type>::value && !sprout::detail::has_mem_next_value::value && !sprout::is_input_iterator::value && sprout::detail::has_function_call::value >::type > { public: static SPROUT_CONSTEXPR decltype(std::declval()()) generate_next_value(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(std::declval()()) { return gen(); } }; template struct generate_next_value_impl< Gen, typename std::enable_if< std::is_reference::value && std::is_const::type>::value && !sprout::detail::has_mem_next_value::value && !sprout::is_input_iterator::value && !sprout::detail::has_function_call::value >::type > { public: static SPROUT_CONSTEXPR decltype(sprout::generators::next_value(sprout::generators::next_generator(std::declval()))) generate_next_value(Gen gen) SPROUT_NOEXCEPT_IF_EXPR(sprout::generators::next_value(sprout::generators::next_generator(std::declval()))) { return sprout::generators::next_value(sprout::generators::next_generator(gen)); } }; } // namespace detail } // namespace sprout namespace sprout_generator_detail { template inline SPROUT_CONSTEXPR decltype(sprout::detail::generate_next_value_impl::generate_next_value(std::declval())) generate_next_value(Gen& gen) SPROUT_NOEXCEPT_IF_EXPR(sprout::detail::generate_next_value_impl::generate_next_value(std::declval())) { return sprout::detail::generate_next_value_impl::generate_next_value(gen); } template inline SPROUT_CONSTEXPR typename std::enable_if< !std::is_const::value && !std::is_volatile::value && !std::is_reference::value, decltype(sprout::detail::generate_next_value_impl::generate_next_value(std::declval())) >::type generate_next_value(Gen&& gen) SPROUT_NOEXCEPT_IF_EXPR(sprout::detail::generate_next_value_impl::generate_next_value(std::declval())) { return sprout::detail::generate_next_value_impl::generate_next_value(sprout::move(gen)); } template inline SPROUT_CONSTEXPR decltype(sprout::detail::generate_next_value_impl::generate_next_value(std::declval())) generate_next_value(Gen const& gen) SPROUT_NOEXCEPT_IF_EXPR(sprout::detail::generate_next_value_impl::generate_next_value(std::declval())) { return sprout::detail::generate_next_value_impl::generate_next_value(gen); } } // namespace sprout_generator_detail #endif // #ifndef SPROUT_GENERATOR_DETAIL_NEXT_VALUE_HPP