std::copy n elements or to the end

我只是一个虾纸丫 提交于 2019-12-03 01:25:28

If you have access to the whole data structure, and therefore its size, you can use the following:

std::vector<int> v1, v2;
std::copy_n(v2.begin(), std::min(NUM, v2.size()), std::back_inserter(v1));

If you have access to only iterators, I don't know how to do this using only std functions without calculating the distance. This is cheap for random-access iterators but duplicates work for other types.

std::vector<int>::iterator i_begin, i_end, o_begin;
std::copy_n(i_begin, std::min(NUM, std::distance(i_begin, i_end)), o_begin);

I would go for something like this:

template <class InputIt, class OutputIt>
OutputIt copy_n_max(InputIt begin, InputIt end, OutputIt last, size_t count)
{
    return std::copy_if(begin, 
                        end, 
                        last, 
                        [&count](typename std::iterator_traits<InputIt>::reference) -> bool 
                        {
                            if (count > 0)
                            {
                                --count;
                                return true;
                            }
                            return false;
                        });
}

Using copy_if predicate to check whether or not enough of this input was copied. Main advantage I see here is no extra std::distance involved.

Live example on IDEOne

There's a simple way to use the std::copy_if-overload added by C++11 for your task (Only needs InputIterators):

template< class InputIt, class Size, class OutputIt>
OutputIt myCopy_n(InputIt first, InputIt last, Size count, OutputIt result)
{
    return std::copy_if(first, last, result,
        [&](typename std::iterator_traits<InputIt>::reference)
        {return count && count--;});
}

BTW: It gets even better in C++14, no need for a variable or such a complicated argument:

std::copy_if(first, last, result,
    [count = some_complicated_expression](auto&&) mutable
    {return count && count--;});

You can use copy_if with a custom predicator, and it works for older versions of c++.

#include <algorithm>
#include <iostream>
#include <vector>
#include <iterator>


struct LimitTo
{
    LimitTo( const int n_ ) : n(n_)
    {}

    template< typename T >
    bool operator()( const T& )
    {
        return n-->0;
    }

    int n;
};

int main()
{
    std::vector< int > v1{ 1,2,3,4,5,6,7,8 };
    std::vector< int > v2;

    std::copy_if( std::begin(v1), std::end(v1), std::back_inserter(v2), LimitTo(3) );

    std::copy( std::begin(v1), std::end(v1), std::ostream_iterator<int>(std::cout,", ") );
    std::cout << std::endl;
    std::copy( std::begin(v2), std::end(v2), std::ostream_iterator<int>(std::cout,", ") );
    std::cout << std::endl;
}

This example copies n elements, using predicator LimitTo.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!