Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using const std::unique_ptr for pimpl idiom

Tags:

c++

c++11

c++17

In Herb Sutter's talk at CppCon16 he suggested writing pimpl idiom with const std::unique_ptr (roughly 10 minutes in).

How is this supposed to work with move constructors/assignments? Is there something in c++17? I couldn't find anything.

like image 795
Denis Yaroshevskiy Avatar asked Sep 26 '16 13:09

Denis Yaroshevskiy


People also ask

Why would you use Unique_ptr instead of a raw pointer when writing a Pimpl class?

unique_ptr is an excellent choice for local dynamic objects which will be destructed even in case of exceptions, but for "attributes", you save nothing but the possibility of getting UB if you don't remember you have to rewrite the move assignment operator.


2 Answers

If your class is supposed to be never-empty, a non-const unique ptr (with default move/assigns) is not appropriate. The move ctor and move assign will both empty the rhs.

A const unique ptr will disable these automatic methods, and if you want move you will have to write it within the impl (and a bit of glue outside).

I would personally write a value ptr with the semantics I want (then let compiler write the glue), but starting with a const unique_ptr sounds reasonable as a first pass.

If you relax the never-empty, and make it almost never-empty, you now have to reason about preconditions of a lot of methods, and possible knock-on bugs.

The biggest cost of this technique, difficulty in returning values, goes away with C++17.

like image 159
Yakk - Adam Nevraumont Avatar answered Nov 02 '22 08:11

Yakk - Adam Nevraumont


How is this suppose to work with move constructors/assignments?

Move constructors:

The implicitly-declared or defaulted move constructor for class T is defined as deleted if any of the following conditions are true:

  • T has non-static data members that cannot be moved (have deleted, inaccessible, or ambiguous move constructors)

const std::unique_ptr is such a data member because of const.

If const is dropped the compiler generates the move constructor and assignment, but not the copying ones.


Herb explains why he uses const unique_ptr:

non-const can work too, but it is more brittle because default move semantics are probably incorrect.

With const member it is more robust because const members must be initialized in the constructor. And const documents that the implementation of the object does not change, it is not State or Strategy design pattern.

like image 23
Maxim Egorushkin Avatar answered Nov 02 '22 08:11

Maxim Egorushkin