Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I not move unique_ptr from a set to a function argument using an iterator?

I have a set of unique_ptr instances and want to pass all of them as an argument to a function. Example demonstrated by below code.

#include <memory>
#include <set>
#include <vector>

using std::set;
using std::unique_ptr;
using std::vector;

void doStuff(unique_ptr<int> ptr)
{
  // doing stuff...
}

int main()
{
  vector<unique_ptr<int>> ptrVector;
  set<unique_ptr<int>> ptrSet;

  for (auto cur = ptrVector.begin(); cur != ptrVector.end(); cur++)
  {
    doStuff(std::move(*cur));
  }

  for (auto cur = ptrSet.begin(); cur != ptrSet.end(); cur++)
  {
    doStuff(std::move(*cur));
  }

  return 0;
}

This results in the following compiler error (GCC 4.8.1):

uptrfncall.cpp: In function ‘int main()’:
uptrfncall.cpp:27:25: error: use of deleted function ‘std::unique_ptr::unique_ptr(const std::unique_ptr&) [with _Tp = int; _Dp = std::default_delete]’
  doStuff(std::move(*cur)); // line 25, compiler error
                         ^
In file included from /usr/include/c++/4.8/memory:81:0,
                 from uptrfncall.cpp:1:
/usr/include/c++/4.8/bits/unique_ptr.h:273:7: error: declared here
       unique_ptr(const unique_ptr&) = delete;
       ^
uptrfncall.cpp:9:10: error:   initializing argument 1 of ‘void doStuff(std::unique_ptr)’
     void doStuff(unique_ptr ptr)
          ^

Note that it works flawlessly for the vector but not for the set. As the set is not const, the begin() call should not return a const_iterator so it should be possible to move the values when dereferencing the iterator. Why does this not compile?

like image 335
Chris Avatar asked Aug 13 '13 05:08

Chris


People also ask

Can you move a unique_ptr?

A unique_ptr can only be moved. This means that the ownership of the memory resource is transferred to another unique_ptr and the original unique_ptr no longer owns it. We recommend that you restrict an object to one owner, because multiple ownership adds complexity to the program logic.

What does unique_ ptr do in c++?

std::unique_ptr is a smart pointer that owns and manages another object through a pointer and disposes of that object when the unique_ptr goes out of scope. The object is disposed of, using the associated deleter when either of the following happens: the managing unique_ptr object is destroyed.

What is the scope of unique_ptr?

An​ unique_ptr has exclusive ownership of the object it points to and ​will destroy the object when the pointer goes out of scope. A unique_ptr explicitly prevents copying of its contained pointer.


2 Answers

The set may not be const, but the elements within it are. You cannot modify a set's elements, as it wouldn't be able to guarantee it's maintaining its invariants.

like image 189
GManNickG Avatar answered Sep 24 '22 17:09

GManNickG


Code line std::set is created basing on Red-Black tree and set's iterator type is same as tree's key type, obviously you cannot change key's value.

like image 30
Ruben_Lv Avatar answered Sep 22 '22 17:09

Ruben_Lv