copy(...) 和 copy(seq, ...) 之间的关系

Posted

技术标签:

【中文标题】copy(...) 和 copy(seq, ...) 之间的关系【英文标题】:Relationship between copy(...) and copy(seq, ...) 【发布时间】:2019-08-15 18:07:58 【问题描述】:

std::copy 有和没有执行策略参数之间是否存在正式关系?无论是在实践中还是在标准中。

例如,是不是这样简单,

namespace std
    template<class It>
    It copy(std::execution::sequenced_policy, It first, It last, It d_first)
        return std::copy(first, last, d_first);
    

namespace std
    template<class It>
    It copy(std::execution::sequenced_policy, It first, It last, It d_first)
    //    using std::copy; // may not be needed
        return copy(first, last, d_first);
    

请注意,在第一个版本中意味着我还需要重载copy(par::seq, ...)

还是这样

namespace std
    template<class It>
    It copy(std::execution::sequenced_policy, It first, It last, It d_first)
        ... not defined at all in terms of other `copy(It, ...)` or `std::copy(It, ...)`
    

原因是我想为一种特殊类型的迭代器重载复制算法(在自定义命名空间中)。

【问题讨论】:

【参考方案1】:

[execpol.seq] 中提到的一个区别是

在执行并行算法的过程中, execution​::​sequenced_­policy 策略,如果调用一个元素 访问函数通过未捕获的异常退出,terminate() 应为 调用。

演示:

#include <execution>
#include <iostream>
#include <stdexcept>

struct C 
    C() 
    C& operator=(const C&) 
        throw std::runtime_error("copy failed");
    
;

int main() 
    C a[1];
    C b[1];

    try 
        std::copy(std::begin(a), std::end(a), std::begin(b));
     catch(const std::runtime_error& ex) 
        std::cout << "Exception: " << ex.what() << "\n";
    

    try 
        std::copy(std::execution::seq, std::begin(a), std::end(a), std::begin(b));
     catch(const std::runtime_error& ex) 
        std::cout << "Exception: " << ex.what() << "\n";
    

可能的输出:

Exception: copy failed
terminate called after throwing an instance of 'std::runtime_error'
  what():  copy failed
Aborted (core dumped)

【讨论】:

好的,这是一个非常有用的细节。这也降低了一个根据另一个实现的可能性,但它仍然是可能的(理想的?)。 @alfC 我认为标准允许使用 std::execution::sequenced_policy 调用的函数使用没有 ExecutionPolicy 的函数版本,但如果抛出异常,则必须使用 terminate()。尽管元素访问是按顺序完成的,但可能允许并行算法实现并行执行操作,但这只是代表我的猜测。 谢谢。这就说得通了。我的最终问题是我是否需要为自定义迭代器同时重载 copy 和 copy(seq。这还取决于 copy(seq 是否对 ADL 友好。可能它不是标准的,我只能靠我自己。 @alfC 哦,我已经制作了很多自定义迭代器,但我还没有为 copy 制作重载。当使用带有copy(par 的自定义迭代器时,我注意到它做了一些我没有准备好的奇怪的事情。如果我没记错的话,我测试过的par 实现在启动线程之前在范围内循环了一次,然后它实际上完成了工作。为未知范围创建迭代器很棘手,如果我没记错的话,it==end() 将取决于任何线程找到的结果... 不幸的是,必须重新发明井以实现具有错误处理和中断条件的并行算法。我认为必须有一种方法可以优雅地做到这一点,甚至可能没有分配。

以上是关于copy(...) 和 copy(seq, ...) 之间的关系的主要内容,如果未能解决你的问题,请参考以下文章

xcopy和copy有什么区别?

Python实现冒泡选择插入快速排序

。copy和.copy()之间的差异

std::copy、std::copy_backward 和重叠范围

关于iOS的深copy和浅copy 以及copy 和 strong 的区别

copy 和xcopy哪个速度快