std :: copy n元素或结尾

aiv*_*020 22 c++ stl-algorithm

我想复制N个元素.

template< class InputIt, class Size, class OutputIt>
OutputIt myCopy_n(InputIt first, InputIt last, Size count, OutputIt result)
{
    Size c = count;
    while (first != last && c > 0) {
        *result++ = *first++;
        --c;
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

有没有办法用std函数做到这一点?我还可以:

template< class InputIt, class Size, class OutputIt>
OutputIt myCopy_n(InputIt first, InputIt last, Size count, OutputIt result)
{
    if(std::distance(first, last) > count)
        return std::copy_n(first,count,result);
    return std::copy(first,last,result);
}
Run Code Online (Sandbox Code Playgroud)

然而,除了麻烦之外,它超过了范围两次(距离,复制).如果我正在使用变换迭代器或过滤迭代器,那么这些是对我的过滤器/变换函数的O(N)个不必要的调用.

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)
                        { return count--> 0; });
}

int main()
{
    std::vector<int> v({1,2,3,4,5,6,7,8,9}), out;
    copy_n_max(v.begin(), v.end(), std::back_inserter(out), 40);
    for(int i : out) std::cout <<i << " ,";
}
Run Code Online (Sandbox Code Playgroud)

输出1,2,3,4,5,6,7,8,9,

然而,这将持续到结束,而不是计算时间.所以,更多不必要的调用我的过滤器/转换功能......

Nei*_*irk 14

如果您可以访问整个数据结构,因此可以访问其大小,则可以使用以下命令:

std::vector<int> v1, v2;
std::copy_n(v2.begin(), std::min(NUM, v2.size()), std::back_inserter(v1));
Run Code Online (Sandbox Code Playgroud)

如果只能访问迭代器,我不知道如何在不计算距离的情况下仅使用std函数.这对随机访问迭代器来说很便宜,但重复可用于其他类型.

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);
Run Code Online (Sandbox Code Playgroud)

  • @ user2232888如果你只有非随机访问迭代器并且性能很关键,我会使用自己的函数. (2认同)

Joh*_*han 8

我会选择这样的东西:

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;
                        });
}
Run Code Online (Sandbox Code Playgroud)

使用copy_if谓词检查是否复制了足够的输入.我在这里看到的主要优点是没有额外的std::distance参与.

IDEOne上的实例


Ded*_*tor 8

有一种简单的方法可以使用std::copy_ifC++ 11为您的任务添加-overload(只需要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--;});
}
Run Code Online (Sandbox Code Playgroud)

BTW:在C++ 14中它变得更好,不需要变量或这么复杂的参数:

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