1

I have the following method:

std::unique_ptr<Req> RequestConverter::SetReg(
    const std::unique_ptr<Req> pb_req, ...) {

I want to return parameter pb_req from the above method. I get this error (with or without std::move):

error: call to deleted constructor of 'std::unique_ptr<Req>'

What's recommended approach ?

Thanks

Ted
  • 379
  • 1
  • 5
  • 18
  • 1
    Is there a reason `pb_req` is marked as `const`? – NathanOliver Jun 07 '17 at 17:39
  • You might have to remove the `const`, but you can `return std::move(pb_req);` OTOH, if you want to do this, you probably really just want to do `void RequestConverter::SetReg(const Req &pb_req, ...)` – Justin Jun 07 '17 at 17:40
  • You probably might just want to pass a reference to a Req-object? – The Techel Jun 07 '17 at 17:42
  • 1
    Possible duplicate of [Returning unique\_ptr from functions](https://stackoverflow.com/questions/4316727/returning-unique-ptr-from-functions) – Oguz Kaan Agac Jun 07 '17 at 23:02

1 Answers1

0

The unique_ptr copy constructor is marked as deleted, i.e. the following

unique_ptr(const unique_ptr&) = delete;

And when you return a const unique_ptr<Req> from your function, the return value is treated as an rvalue, and therefore the exact match for a constructor if available would be

unique_ptr(const unique_ptr&&);

The move constructor does not match const unique_ptr<Req>&& because it requires a non const rvalue reference. And so the closest match is the copy constructor which is deleted, therefore this does not work.

But the question you should be asking yourself is, why do you want to mark the unique_ptr to be const in the first place? A const unique_ptr means that the pointer is const, and not the pointed to thing. If you want a unique_ptr to const, you should do unique_ptr<const Req> instead.

Curious
  • 20,870
  • 8
  • 61
  • 146
  • Thanks for the quick reply. I removed the const: https://pastebin.com/mZw26QGk Here is caller: https://pastebin.com/U9vX5yf9 I got this error: https://pastebin.com/4BP6Du74 – Ted Jun 07 '17 at 18:06
  • Two things, 1. you don't have to return a local value in a function by `std::move()`ing it, its an anti pattern, it just so happens that in this case it does not make a difference as the standard does not allow elision from function parameters (and that too is just probably because someone has not implemented it yet https://stackoverflow.com/questions/43163801/why-does-for-each-return-function-by-move). Just return if by value, and it will be treated as an rvalue implicitly – Curious Jun 07 '17 at 18:10
  • 2. What you are doing after calling the function is attaching it a callback with the `->action()` method, this presumably returns a functor, or a reference or a copy. And using this to initialize the variable on the left hand side of the expression tries to get the lambda that you have passed to the `->action()` method to be copied, but this is not possible since you have moved a value into the lambda in the capture list. And when you move a value into a lambda it cannot be copied anymore. Let me know if something still does not make sense – Curious Jun 07 '17 at 18:12
  • Here is updated code: https://pastebin.com/iUeRJKS4 I got linker error: https://pastebin.com/Wakr7zWW I wonder what I missed. Thanks – Ted Jun 07 '17 at 20:52
  • Here is the gcc version I am using: gcc (Ubuntu 5.3.1-14ubuntu2) 5.3.1 20160413 – Ted Jun 08 '17 at 00:43
  • @Ted the linker error seems to be unrelated to the error you have talked about in your post. That has to do with some `hbase::` function not being compiled. – Curious Jun 08 '17 at 06:15
  • Yeah - different problem. – Ted Jun 08 '17 at 18:06