#ifndef SPROUT_ALGORITHM_FIXED_GENERATE_HPP #define SPROUT_ALGORITHM_FIXED_GENERATE_HPP #include #include #include #include #include #include namespace sprout { namespace fixed { namespace detail { template SPROUT_CONSTEXPR inline typename std::enable_if< InitSize == sizeof...(Args) + 1, typename sprout::fixed_container_traits::value_type >::type call_gen( Generator gen, Head const& head, Args const&... args ) { return gen(head, args...); } template SPROUT_CONSTEXPR inline typename std::enable_if< InitSize != sizeof...(Args) + 1, typename sprout::fixed_container_traits::value_type >::type call_gen( Generator gen, Head const& head, Args const&... args ) { return call_gen(gen, args...); } template SPROUT_CONSTEXPR inline typename std::enable_if< sprout::fixed_container_traits::fixed_size == sizeof...(Args), typename sprout::fixed::result_of::algorithm::type >::type generate_impl_4( Container const& cont, Args const&... args ) { return sprout::remake_clone(cont, sprout::size(result), args...); } template SPROUT_CONSTEXPR inline typename std::enable_if< sprout::fixed_container_traits::fixed_size != sizeof...(Args), typename sprout::fixed::result_of::algorithm::type >::type generate_impl_4( Container const& cont, Args const&... args ) { return generate_impl_4(cont, args..., *(sprout::fixed_begin(cont) + sizeof...(Args))); } template SPROUT_CONSTEXPR inline typename std::enable_if< sprout::fixed_container_traits::fixed_size == sizeof...(Args), typename sprout::fixed::result_of::algorithm::type >::type generate_impl_3( Container const& cont, Generator gen, typename sprout::fixed_container_traits::difference_type offset, Args const&... args ) { return sprout::remake_clone(cont, sprout::size(result), args...); } template SPROUT_CONSTEXPR inline typename std::enable_if< sprout::fixed_container_traits::fixed_size != sizeof...(Args), typename sprout::fixed::result_of::algorithm::type >::type generate_impl_3( Container const& cont, Generator gen, typename sprout::fixed_container_traits::difference_type offset, Args const&... args ) { return sizeof...(Args) < offset ? generate_impl_3(cont, gen, offset, args..., call_gen(gen, args...)) : generate_impl_4(cont, args...) ; } template SPROUT_CONSTEXPR inline typename std::enable_if< sizeof...(Args) == 0, typename sprout::fixed::result_of::algorithm::type >::type generate_impl_2_drop( Container const& cont, typename sprout::fixed_container_traits::size_type dropped_size, Head const& head, Args const&... args ) { return sprout::remake_clone(cont, sprout::size(result), args...); } template SPROUT_CONSTEXPR inline typename std::enable_if< sizeof...(Args) != 0, typename sprout::fixed::result_of::algorithm::type >::type generate_impl_2_drop( Container const& cont, typename sprout::fixed_container_traits::size_type dropped_size, Head const& head, Args const&... args ) { return sizeof...(Args) + 1 != dropped_size ? generate_impl_2_drop(cont, dropped_size, args...) : generate_impl_4(cont, head, args...) ; } template SPROUT_CONSTEXPR inline typename sprout::fixed::result_of::algorithm::type generate_impl_2( Container const& cont, Generator gen, typename sprout::fixed_container_traits::difference_type offset, typename sprout::fixed_container_traits::size_type size, std::size_t remain, Head const& head, Args const&... args ) { return InitSize - remain != size ? (remain > 1 ? generate_impl_2(cont, gen, offset, size, remain - 1, args..., head) : generate_impl_3(cont, gen, offset + size, args..., head) ) : generate_impl_2_drop(cont, offset + size, head, args...) ; } template SPROUT_CONSTEXPR inline typename std::enable_if< sprout::fixed_container_traits::fixed_size == sizeof...(Args), typename sprout::fixed::result_of::algorithm::type >::type generate_impl_1( Container const& cont, Generator gen, typename sprout::fixed_container_traits::difference_type offset, typename sprout::fixed_container_traits::size_type size, Args const&... args ) { return generate_impl_2(cont, gen, offset, size, InitSize, args...); } template SPROUT_CONSTEXPR inline typename std::enable_if< sprout::fixed_container_traits::fixed_size != sizeof...(Args), typename sprout::fixed::result_of::algorithm::type >::type generate_impl_1( Container const& cont, Generator gen, typename sprout::fixed_container_traits::difference_type offset, typename sprout::fixed_container_traits::size_type size, Args const&... args ) { return sizeof...(Args) - InitSize < offset ? generate_impl_1(cont, gen, offset, size, args..., *(sprout::fixed_begin(cont) + sizeof...(Args) - InitSize)) : generate_impl_2(cont, gen, offset, size, InitSize, args...) ; } template SPROUT_CONSTEXPR inline typename sprout::fixed::result_of::algorithm::type generate_impl( Container const& cont, Generator gen, typename sprout::fixed_container_traits::size_type size, Inits const&... inits ) { return generate_impl_1(cont, gen, sprout::fixed_begin_offset(cont), size, inits...); } } // namespace detail // // generate // template SPROUT_CONSTEXPR inline typename sprout::fixed::result_of::algorithm::type generate( Container const& cont, Generator gen, Inits const&... inits ) { return sprout::fixed::detail::generate_impl(cont, gen, sprout::size(cont), inits...); } } // namespace fixed using sprout::fixed::generate; } // namespace sprout #endif // #ifndef SPROUT_ALGORITHM_FIXED_GENERATE_HPP