/*============================================================================= 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_ALGORITHM_FIXED_RECURRENCE_HPP #define SPROUT_ALGORITHM_FIXED_RECURRENCE_HPP #include #include #include #include #include #include #include #include #include namespace sprout { namespace fixed { namespace detail { template inline SPROUT_CONSTEXPR typename std::enable_if< InitSize == 0, typename sprout::container_traits::value_type >::type call_gen(Generator const& gen, Args const&...) { return gen(); } template inline SPROUT_CONSTEXPR typename std::enable_if< InitSize != 0 && InitSize == sizeof...(Args) + 1, typename sprout::container_traits::value_type >::type call_gen(Generator const& gen, Head const& head, Args const&... args) { return gen(head, args...); } template inline SPROUT_CONSTEXPR typename std::enable_if< InitSize != 0 && InitSize != sizeof...(Args) + 1, typename sprout::container_traits::value_type >::type call_gen(Generator const& gen, Head const&, Args const&... args) { return call_gen(gen, args...); } template inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm::type recurrence_impl_drop( Container const& cont, Generator const&, typename sprout::container_traits::size_type ) { return sprout::detail::container_complate(cont); } template inline SPROUT_CONSTEXPR typename std::enable_if< (sprout::container_traits::static_size >= sizeof...(Inits) + 1), typename sprout::fixed::results::algorithm::type >::type recurrence_impl_drop( Container const& cont, Generator const& gen, typename sprout::container_traits::size_type size, Head const& head, Inits const&... inits ) { return size < sizeof...(Inits) + 1 ? sprout::fixed::detail::recurrence_impl_drop(cont, gen, size, inits...) : sprout::detail::container_complate(cont, head, inits...) ; } template inline SPROUT_CONSTEXPR typename std::enable_if< (sprout::container_traits::static_size < sizeof...(Inits) + 1), typename sprout::fixed::results::algorithm::type >::type recurrence_impl_drop( Container const& cont, Generator const& gen, typename sprout::container_traits::size_type size, Head const&, Inits const&... inits ) { return sprout::fixed::detail::recurrence_impl_drop(cont, gen, size, inits...); } template inline SPROUT_CONSTEXPR typename std::enable_if< sprout::container_traits::static_size == sizeof...(Args), typename sprout::fixed::results::algorithm::type >::type recurrence_impl_1( Container const& cont, Generator const&, typename sprout::container_traits::size_type, Args const&... args ) { return sprout::remake(cont, sprout::size(cont), args...); } template inline SPROUT_CONSTEXPR typename std::enable_if< sprout::container_traits::static_size != sizeof...(Args), typename sprout::fixed::results::algorithm::type >::type recurrence_impl_1( Container const& cont, Generator const& gen, typename sprout::container_traits::size_type size, Args const&... args ) { return sizeof...(Args) < size ? sprout::fixed::detail::recurrence_impl_1( cont, gen, size, args..., sprout::fixed::detail::call_gen(gen, args...) ) : sprout::detail::container_complate(cont, args...) ; } template inline SPROUT_CONSTEXPR typename std::enable_if< (sprout::container_traits::static_size > sizeof...(Inits)), typename sprout::fixed::results::algorithm::type >::type recurrence_impl( Container const& cont, Generator const& gen, typename sprout::container_traits::size_type size, Inits const&... inits ) { return sizeof...(Inits) < size ? sprout::fixed::detail::recurrence_impl_1(cont, gen, size, inits...) : sprout::fixed::detail::recurrence_impl_drop(cont, gen, size, inits...) ; } template inline SPROUT_CONSTEXPR typename std::enable_if< (sprout::container_traits::static_size <= sizeof...(Inits)), typename sprout::fixed::results::algorithm::type >::type recurrence_impl( Container const& cont, Generator const& gen, typename sprout::container_traits::size_type size, Inits const&... inits ) { return sprout::fixed::detail::recurrence_impl_drop(cont, gen, size, inits...); } } // namespace detail // // recurrence // template inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm::type recurrence(Container const& cont, Generator const& gen, Inits const&... inits) { return sprout::fixed::detail::recurrence_impl(cont, gen, sprout::size(cont), inits...); } template inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm::type recurrence(Generator const& gen, Inits const&... inits) { return sprout::fixed::recurrence(sprout::pit(), gen, inits...); } } // namespace fixed using sprout::fixed::recurrence; } // namespace sprout #endif // #ifndef SPROUT_ALGORITHM_FIXED_RECURRENCE_HPP