I'm able to pass a std::unique_ptr rvalue as a parameter to a function like below because of copy elision. Is the copy guaranteed to be elided by the C++11 standard or can this fail to compile on some implementations?

void take_unique_ptr_by_value(std::unique_ptr<int> sp) {
  cout << "Value is " << *sp.get() << std::endl;
// I am able to call the function above like this:

2 Answers

Jarod42 On

because of copy elision

No, it is because of move constructor.

In addition, copy elision is just a optimization and still requires the code to be valid. So

struct S
    S() = default;
    S(const S&) = delete;
    S(S&&) = delete;

S s = S(); // Won't compile prior C++17

C++17 introduces "guarantied copy elision" (in some contexts) which remove this constraint.

More details on copy_elision's doc

Mike Sweeney On

To piece together some of the answers more explicitly as @Jarod42 mentioned even if copy elision were to take place the copy/move constructor being elided still has to exist. Secondly, what I was forgetting is that the parameter I'm passing in is an rvalue so it will invoke the move constructor if it needs to be "copied". So copy elision or not the example code is correct because std::unique_ptr has a move constructor and I am passing in an rvalue. This other answer is pretty comprehensive.