std::experimental::ranges::copy, std::experimental::ranges::copy_if

来自cppreference.com
< cpp‎ | experimental‎ | ranges
 
 
实验性
技术规范
文件系统库 (文件系统 TS)
库基础 (库基础 TS)
库基础 2 (库基础 TS v2)
库基础 3 (库基础 TS v3)
并行扩展 (并行 TS)
并行扩展 2 (并行 TS v2)
并发扩展 (并发 TS)
并发扩展 2 (并发 TS v2)
概念 (概念 TS)
范围 (范围 TS)
反射 (反射 TS)
数学特殊函数 (特殊函数 TR)
实验性非 TS 功能特性
模式匹配
线性代数
std::execution
契约
2D 图形
 
 
 
template< InputIterator I, Sentinel<I> S, WeaklyIncrementable O >

    requires IndirectlyCopyable<I, O>
ranges::tagged_pair<tag::in(I), tag::out(O)>

    copy( I first, S last, O result );
(1) (范围 TS)
template< InputRange R, WeaklyIncrementable O >

    requires IndirectlyCopyable<ranges::iterator_t<R>, O>
ranges::tagged_pair<tag::in(ranges::safe_iterator_t<R>), tag::out(O)>

    copy( R&& r, O result );
(2) (范围 TS)
template< InputIterator I, Sentinel<I> S, WeaklyIncrementable O,

          class Proj = ranges::identity,
          IndirectUnaryPredicate<projected<I, Proj>> Pred >
    requires IndirectlyCopyable<I, O>
ranges::tagged_pair<tag::in(I), tag::out(O)>

    copy_if( I first, S last, O result, Pred pred, Proj proj = Proj{} );
(3) (范围 TS)
template< InputRange R, WeaklyIncrementable O,

          class Proj = ranges::identity,
          IndirectUnaryPredicate<projected<ranges::iterator_t<R>, Proj>> Pred >
    requires IndirectlyCopyable<iterator_t<R>, O>
ranges::tagged_pair<tag::in(ranges::safe_iterator_t<R>), tag::out(O)>

    copy_if( R&& r, O result, Pred pred, Proj proj = Proj{} );
(4) (范围 TS)

复制源范围([firstlast)r)中的元素到始于 result 的目标范围中,从源范围的首元素开始,后续到末元素。

1) 复制范围 [firstlast) 中的所有元素。对每个非负整数 n < (last - first) 进行 *(result + n) = *(first + n)。若 result 在范围 [firstlast) 内则行为未定义。此情况下可用 ranges::copy_backward 代替。
2)(1),但以 r 为源范围,如同用 ranges::copy(ranges::begin(rng), ranges::end(rng), result);,但不会复制 result
3) 仅复制那些谓词 pred 在投影 proj 所投影的元素值返回 true 的元素。保持复制后的元素顺序。若源与目标范围重叠则行为未定义。
4)(3),但以 r 为源范围,如同用 ranges::copy_if(ranges::begin(rng), ranges::end(rng), result, pred, proj);,但不会复制 resultpredproj

尽管声明描述如上,算法声明的模板形参的实际数量和顺序是未指定的。从而若在调用算法时使用显式模板实参,则程序很可能不可移植。

参数

first, last - 要复制的元素范围
rng - 要复制的元素范围
result - 目标范围的起始
pred - 要应用到投影后元素的谓词
proj - 要应用到元素的投影

返回值

含有以下两个成员的 tagged_pair 对象:

  • 第一成员有标签 tag::in,为源范围的尾后迭代器(即比较等于哨位 lastI 类型迭代器)。
  • 第二成员有标签 tag::out,为结果范围的尾后迭代器。

复杂度

1) 恰好赋值 ranges::distance(first, last) 次。
2) 恰好赋值 ranges::distance(rng) 次。
3) 恰好应用 ranges::distance(first, last) 次对应的投影和谓词。
3) 恰好应用 ranges::distance(rng) 次对应的投影和谓词。

可能的实现

版本一
template<InputIterator I, Sentinel<I> S, WeaklyIncrementable O>
    requires IndirectlyCopyable<I, O>()
ranges::tagged_pair<tag::in(I), tag::out(O)>
    copy(I first, S last, O result)
{
    for (; first != last; ++first, (void)++result)
        *result = *first;
    return {first, result};
}
版本二
template<InputRange R, WeaklyIncrementable O>
    requires IndirectlyCopyable<ranges::iterator_t<R>, O>()
ranges::tagged_pair<tag::in(ranges::safe_iterator_t<R>), tag::out(O)>
    copy(R&& r, O result)
{
   return ranges::copy(ranges::begin(r), ranges::end(r), result);
}
版本三
template<InputIterator I, Sentinel<I> S, WeaklyIncrementable O,
         class Proj = ranges::identity,
         IndirectUnaryPredicate<projected<I, Proj>> Pred>
    requires IndirectlyCopyable<I, O>()
ranges::tagged_pair<tag::in(I), tag::out(O)>
    copy_if(I first, S last, O result, Pred pred, Proj proj = Proj{})
{
    for (; first != last; ++first)
        if (ranges::invoke(pred, ranges::invoke(proj, *first)))
        {
            *result = *first;
            ++result;
        }
    return {first, result};
}
版本四
template<InputRange R, WeaklyIncrementable O,
         class Proj = ranges::identity,
         IndirectUnaryPredicate<projected<ranges::iterator_t<R>, Proj>> Pred>
    requires IndirectlyCopyable<ranges::iterator_t<R>, O>()
ranges::tagged_pair<tag::in(ranges::safe_iterator_t<R>), tag::out(O)>
    copy_if(R&& r, O result, Pred pred, Proj proj = Proj{})
{
    return ranges::copy_if(ranges::begin(r), ranges::end(r), result, pred, proj);
}

示例

下列代码用 copy 复制一个 vector 的内容给另一个,并显示结果 vector

#include <experimental/ranges/algorithm>
#include <experimental/ranges/iterator>
#include <iostream>
#include <numeric>
#include <vector>
 
int main()
{
    // 参阅 http://zh.cppreference.com/w/cpp/language/namespace_alias
    namespace ranges = std::experimental::ranges;
 
    std::vector<int> from_vector(10);
    std::iota(from_vector.begin(), from_vector.end(), 0);
 
    std::vector<int> to_vector;
    ranges::copy_if(from_vector.begin(), from_vector.end(),
                    ranges::back_inserter(to_vector),
                    [](const auto i)
                    {
                       return i % 3;
                    });
// 或替用的
//  std::vector<int> to_vector(from_vector.size());
//  std::copy(from_vector, to_vector.begin());
 
    std::cout << "to_vector 包含: ";
 
    ranges::copy(to_vector, ranges::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
}

输出:

to_vector 包含: 1 2 4 5 7 8

参阅

将某一范围的元素复制到一个新的位置
(函数模板)
按从后往前的顺序复制一个范围内的元素
(函数模板)
创建一个范围的逆向副本
(函数模板)
将一定数目的元素复制到一个新的位置
(函数模板)
将一个特定值赋值给一个元素范围
(函数模板)
复制元素范围,忽略满足特定判别标准的元素
(函数模板)