4

It is my understanding that the primary benefit of the pimpl idiom is to hide the data members in the implementation file instead of the header. However, templates need to be fully defined in the header in order for the compiler to instantiate them on demand. In this case, is there any advantage to using the pimpl idiom for a templated class?

Oscar Korz
  • 2,457
  • 1
  • 18
  • 18

5 Answers5

5

While the pimpl idiom doesn't really hide anything when used in a templated class, it does allow you to easily write non-throwing swaps (although with C++11 move semantics this is less of a concern).

  • 1
    +1 Completely forgot about that. In addition to non-throwing cleanliness it is also an efficiency advantage for the swap. This also holds for move semantics, as an opaque class isn't movable as easily as a pimpled class. – Christian Rau Sep 27 '11 at 00:00
  • 1
    Accepted, because this seems to be the only real benefit. – Oscar Korz Sep 30 '11 at 16:24
1

In large projects, decoupling translation units alone is a sufficient reason for pimpl. This works even with templates:

// main interface

template <typename> struct MyImpl;

class TheInterface
{
  MyImpl<int> * pimpl;
};

// implementation

#include "MyImpl.hpp" // heavy-weight template library

// TheInterface implementation
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 1
    Not quite as nicely, though you could separate the implementation of the main template from the class definition and use explicit instantiation in that TU. That only makes sense if you have a small, fixed number of template parameters, though. But otherwise the entire pimpl idea might not be so appropriate anyway. – Kerrek SB Sep 26 '11 at 23:45
  • In a large project the pimpl idiom is a good way to make the project even larger. The result is a kind of C# program coded in C++ in which case it would have been better to port to C# directly instead of pimling. Note that compilation speed improvements of the pimpl idiom will be useless where precompiled headers have taken care already. **pimpl is anti C++** – Patrick Fromberg Sep 09 '13 at 23:52
  • Such a shame that using std::unique_ptr>* pimpl does not work and have to use raw pointers – Ghita Nov 15 '13 at 14:41
1

Theres one case that may not strictly be a pimpl idiom, but is similar enough to warrant knowing about. That is to have a typesafe template wrapper over a non-typesafe version.

class MapBase
{
   public:
     void* getForKey(const std::string & k);
     void setForKey(const std::string & k, void * v);
     ...
};

template<typename T>
class MyMap
{
  public:
    T* getForKey(const std::string &k) { return (T*)base_.getForKey(k); }
    void setForKey( const std::string &k, const T* v) { base_.setForKey(k, T*v); }
  private:
   MapBase base_;
};

Now any use of MyMap<T> doesn't need to be exposed to the internals of MapBase, and you only get one implementation of the guts of those functions. I'd also consider making MapBase be an abstract base class to make the decoupling even stronger.

As I said, its not exactly a pimpl, but it solves may of the same issues in a similar way.

Michael Anderson
  • 70,661
  • 7
  • 134
  • 187
0

I think, if you extend the idiom a bit, you could get at least a bit out of it in some cases. In a template not every operation must necessarily depend on the template parameters. So you can inherit from a Impl class, that itself uses the pimpl idiom, something like this:

struct FooPimpl;

class FooImpl {
  protected:
    FooPimpl* pimpl;
  public:
    void myCommonInterfaceMethod();
};

template <typename T> class Foo : public FooImpl {
  // stuff that depends on T
};

Of course, this depends greatly on the circumstances. But I see the pimpl idiom working in a template class context.

bitmask
  • 32,434
  • 14
  • 99
  • 159
0

it's still quite usable - consider an auto or shared pointer, which is a template and quite usable for solving and implementing PIMPL. whether it's the best solution depends on the problem.

templates need to be fully defined in the header in order for the compiler to instantiate them on demand.

you can declare an the template's members and interface, then in your type's cpp file, you can #include the necessary definitions of the specializations and use them there.

justin
  • 104,054
  • 14
  • 179
  • 226