0
votes

The boost documentation page reads

scoped_ptr cannot be used in C++ Standard Library containers. Use shared_ptr if you need a smart pointer that can.

I'm supposing that being non-copyable would be an obstacle for scoped_ptr but since c++11, as far as some containers are concerned, we can :

  • Constuct in place with emplace_back etc
  • Move resources without copying

So what's the reason for scoped_ptr being non useable with STL containers ?

2
Why not use std::unique_ptr instead ? - Jarod42
If C++11 is an option, use std::unique_ptr, which is in every regard superior to scoped_ptr. The latter only existed as a cheap, feasible half-way measure that did as much as it could sanely without move semantics (by contrast with the broken std::auto_ptr). - Kerrek SB
@Jarod42 I'm wondering whether usage is prohibited (so what's the reason ?) or it's just a case of an out of date documentation. - Nikos Athanasiou
@NikosAthanasiou: Anywhere you have a locally scoped scoped_ptr<T>, you can replace it with a unique_ptr<T> const. Anywhere you have a scoped_ptr<T> in a standard container, you can replace it with a unique_ptr<T> and your life will be happier and improved overall. - Mankarse
@Mankarse: At least you could say that code that would break if you replaced boost::scoped_ptr with std::unique_ptr would be pathological. You could do some SFINAE conditional on mobility and switch code paths based on that, but... why? :-) - Kerrek SB

2 Answers

4
votes

The documentation is somewhat out-of-date. Boost.ScopedPtr is an old library, and the maintainers have not cared to keep the documentation in-sync with the latest developments in C++.

In theory a scoped_ptr-like class could work (as evidenced by std::unique_ptr); but in reality, boost::scoped_ptr cannot be usefully used in many standard containers, since it has a private copy constructor and no move constructor. In particular, std::vector and std::deque require that their contents be move-constructible.

scoped_ptr can be used in node-based containers (since such containers do not require that their contents be move-constructible), if only a limited subset of the container's interface is used. Code such as the following is valid:

std::list<boost::scoped_ptr<int>> list;
list.emplace_back(new int(16));

std::map<int, boost::scoped_ptr<int>> map;
map.emplace(
    std::piecewise_construct,
    std::forward_as_tuple(10),
    std::forward_as_tuple(new int(14)));

Even so, it is needlessly painful compared to just using std::unique_ptr (since using std::unique_ptr will allow you to use a far larger proportion of the standard container's interfaces).

3
votes

As state is the doc,

It supplies a basic "resource acquisition is initialization" facility, without shared-ownership or transfer-of-ownership semantics. Both its name and enforcement of semantics (by being noncopyable) signal its intent to retain ownership solely within the current scope.

and

Q. Why doesn't scoped_ptr have a release() member?
A. When reading source code, it is valuable to be able to draw conclusions about program behavior based on the types being used. If scoped_ptr had a release() member, it would become possible to transfer ownership of the held pointer, weakening its role as a way of limiting resource lifetime to a given context.

scope_ptr exists to be safer that the deprecated auto_ptr and to represent RAII. Now in C++11, we have std::unique_ptr to represent unique ownership.