Search code examples
c++c++11stlcopyargument-dependent-lookup

Relationship between copy(...) and copy(seq, ...)


Is there a formal relationship between std::copy with and without an execution policy argument? Either in practice or in the standard.

For example, would it be the case that simply,

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);
    }
}

or

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);
    }
}

Note that in the first version mean that I need to overload copy(par::seq, ...) as well.

or is the case that

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, ...)`
    }
}

The reason is that I want to ADL overload the copy algorithm (in a custom namespace) for a special kind of iterator.


Solution

  • One difference mentioned in [execpol.seq] is

    During the execution of a parallel algorithm with the execution​::​sequenced_­policy policy, if the invocation of an element access function exits via an uncaught exception, terminate() shall be called.

    Demo:

    #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";
        }
    }
    

    Possible output:

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