#ifndef SPROUT_GENERATOR_NEXT_GENERATOR_HPP #define SPROUT_GENERATOR_NEXT_GENERATOR_HPP #include #include #include #include #include #include namespace sprout_adl { sprout::not_found_via_adl next_generator(...); } // namespace sprout_adl namespace sprout_generator_detail { using sprout::tuples::get; using sprout_adl::next_generator; template struct has_mem_next_generator_test { public: template< typename U = T, typename = decltype(std::declval().next_generator()) > static std::true_type test(int); static std::false_type test(...); }; template struct has_mem_next_generator : public decltype(sprout_generator_detail::has_mem_next_generator_test::test(0)) {}; template struct has_adl_next_generator_test { public: template< typename U = T, typename sprout::enabler_if< sprout::is_found_via_adl()))>::value >::type = sprout::enabler > static std::true_type test(int); static std::false_type test(...); }; template struct has_adl_next_generator : public decltype(sprout_generator_detail::has_adl_next_generator_test::test(0)) {}; template struct has_get_next_generator_test { public: template< typename U = T, typename = decltype(get<1>(std::declval())) > static std::true_type test(int); static std::false_type test(...); }; template struct has_get_next_generator : public decltype(sprout_generator_detail::has_get_next_generator_test::test(0)) {}; template struct select_mem_next_generator; template struct select_mem_next_generator< T, typename std::enable_if::value>::type > : public std::true_type {}; template struct select_mem_next_generator< T, typename std::enable_if::value>::type > : public std::false_type {}; template struct select_adl_next_generator; template struct select_adl_next_generator< T, typename std::enable_if< sprout_generator_detail::has_adl_next_generator::value && !sprout_generator_detail::has_mem_next_generator::value >::type > : public std::true_type {}; template struct select_adl_next_generator< T, typename std::enable_if::value && !sprout_generator_detail::has_mem_next_generator::value )>::type > : public std::false_type {}; template struct select_get_next_generator; template struct select_get_next_generator< T, typename std::enable_if< sprout_generator_detail::has_get_next_generator::value && !sprout_generator_detail::has_mem_next_generator::value && !sprout_generator_detail::has_adl_next_generator::value >::type > : public std::true_type {}; template struct select_get_next_generator< T, typename std::enable_if::value && !sprout_generator_detail::has_mem_next_generator::value && !sprout_generator_detail::has_adl_next_generator::value )>::type > : public std::false_type {}; template struct noexcept_next_generator; template struct noexcept_next_generator::value>::type> : public std::integral_constant().next_generator(), false)> {}; template struct noexcept_next_generator::value>::type> : public std::integral_constant()), false)> {}; template struct noexcept_next_generator::value>::type> : public std::integral_constant(std::declval()), false)> {}; template struct next_generator_result; template struct next_generator_result::value>::type> { public: typedef decltype(std::declval().next_generator()) type; }; template struct next_generator_result::value>::type> { public: typedef decltype(next_generator(std::declval())) type; }; template struct next_generator_result::value>::type> { public: typedef decltype(get<1>(std::declval())) type; }; template< typename T, typename sprout::enabler_if::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR typename sprout_generator_detail::next_generator_result::type next_generator_impl(T&& t) SPROUT_NOEXCEPT_EXPR((sprout_generator_detail::noexcept_next_generator::value)) { return sprout::forward(t).next_generator(); } template< typename T, typename sprout::enabler_if::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR typename sprout_generator_detail::next_generator_result::type next_generator_impl(T&& t) SPROUT_NOEXCEPT_EXPR((sprout_generator_detail::noexcept_next_generator::value)) { return next_generator(sprout::forward(t)); } template< typename T, typename sprout::enabler_if::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR typename sprout_generator_detail::next_generator_result::type next_generator_impl(T&& t) SPROUT_NOEXCEPT_EXPR((sprout_generator_detail::noexcept_next_generator::value)) { return get<1>(sprout::forward(t)); } } // namespace sprout_generator_detail namespace sprout { namespace generators { // // next_generator // template inline SPROUT_CONSTEXPR typename sprout_generator_detail::next_generator_result::type next_generator(T&& t) SPROUT_NOEXCEPT_EXPR((sprout_generator_detail::noexcept_next_generator::value)) { return sprout_generator_detail::next_generator_impl(sprout::forward(t)); } } // namespace generators using sprout::generators::next_generator; } // namespace sprout #endif // #ifndef SPROUT_GENERATOR_NEXT_GENERATOR_HPP