Boost logo

Boost :

Subject: [boost] A Pimpl variant
From: vicente.botet (vicente.botet_at_[hidden])
Date: 2010-04-01 16:13:25


Hi,

I don't know if this is the correct ML to talk about this subject, but as there was recently a discussion about wether Boost should or not use Pimpl, I have decided to post this here.

In http://www.gotw.ca/publications/mill05.htm H. Sutter states
"There are four main alternative disciplines:
1. Put all private data (but not functions) into XImpl.
2. Put all private members into XImpl.
3. Put all private and protected members into XImpl.
4. Make XImpl entirely the class that X would have been, and write X as only the public interface made up entirely of simple forwarding functions (another handle/body variant)."

My experience is that I add more private member functions than private member data. I have explored a different variant
5. Put all private funtion and static data (but not instance data) into XImpl. XImpl needs only to store the back pointer.

 While this approach doesn't encapsulates all the private members has some advantages:
* The XImpl class has no inherent instance data, so no space overhead
* The class doesn't needs to store any XImpl pointer as there is no data to maintain, so no need to allocate/deallocate it.
* Reduce the performance overhead of the Pimpl idiom.

The drawbacks are:
* Need to include the headers needed for the private instance data.
* There is yet a minimal performance overhead on the construction of the temporary XImpl class and the derreference of the back pointer.

Next follows an implementation exaple.
* Grant friend access to the private implementation class

class C {
public:
    void f();
    void g();
protected:
 // ...
private:
  struct impl;
  friend struct impl;
  // the private part contains only instance data and virtual functions
  int priv;
};

* Identify the private functions and the private static data and put them on the implementation class

struct C::impl {
  C::impl(C* thisC) : that(*thisC) {}
  void ifct() {
    that.priv = ... // use of private data
    that.g(); // call to a public function
    jfct(); // call another private function
  }
  C& that;
  static int icount;
};

* Prefix all the ex private function calls by impl(this) impl(this).ifct();
* Access without constraints the impl static data impl::icount;

There is a proposal from Francis Glassborow, N1742: Auxiliary class interfaces:<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1742.pdf> that address this problem in a general context.

What do you think of this variant?

Best,
_____________________
Vicente Juan Botet Escribá


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk