Pimpl-idiom in the template; what a smart pointer?

I usually use boost :: scoped_ptr for pimpl (for one reason, because then I get no surprises if I forget to process the copy constructor)

With templates, however, I cannot just put the destructor in the cpp file, where impl is fully defined to fulfill the requirements of scoped_ptr destructor. It works anyway, but I'm not sure if it is guaranteed to work or just by accident. Is there some kind of "best practice" or standard? Is scoped_ptr the best smart pointer for pimpls in disjoint classes?

template <class T> class C { public: C(){} ~C(){} private: boost::scoped_ptr<T> pimpl_; }; 
+6
source share
3 answers

boost::shared_ptr does not require a full definition, except for the instantiation point in the constructor, in the case of Pimpl. boost::shared_ptr not suitable for the pimpl idiom, however, since it gives very unexpected semantics (reference semantics for assignment or copying); if you really need the extra complexity of a smart pointer, boost::scoped_ptr will be more attractive (but this requires a full definition at the point where its destructor is an instance).

Regarding templates, it makes no sense to use the pimpl idiom for the implementation details from the header. In the absence of export all the details of the implementation of the class template must be included everywhere the template is used, so the motivation underlying the pimpl idiom ceases to exist.

+1
source

It just happens that Herb Sutter started writing his GotWs again after a long time. One of the first new ones is associated with Compilation Firewalls.

You can take a look at:

GotW # 100: Compiling Firewalls (Difficulty: 6/10)

and

GotW # 101: Compiling Firewalls, Part 2 (Difficulty: 8/10)

+13
source

Two years later, I understand the situation much better, in the interest of preserving the answers, relevant and relevant, thatโ€™s how I would answer this question today.

The premise of my original question is somewhat flawed. The reason for using pimpl-idiom is to hide implementation details from the compiler. This is done by storing the implementation through an opaque pointer (a pointer to a declared but not defined data type). This can significantly reduce the number of headers needed by other compilers that interact with the class and thereby speed up compilation time. In the case of a template, my question requires that the type T be fully known at the time of creating the instance, which in practice requires that the impl type be fully defined wherever C<ImplType> , which makes this clearly not an example of pimpl -idiom in the classic sense of the word.

There are other reasons for storing class data using a private pointer, for example, it makes it easy to implement move and swap without throwing, and it is also good if your class has to fulfill a strong exception guarantee (see copying and swap idiom What is the copy and swap idiom ? ). On the other hand, it adds a layer of indirection (often leading to a cache miss) with each access to the implant and the allocation / release of the heap when creating and destroying the implication. These can be significant penalties, so this decision should not be considered a silver bullet.

If you can use C ++ 11 then std :: unique_ptr should be used instead of boost :: scoped_ptr.

+2
source

Source: https://habr.com/ru/post/903111/


All Articles