简体   繁体   中英

Is there any advantage to the pimpl idiom with a templated class?

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?

虽然pimpl习惯用法在模板化类中使用时并没有真正隐藏任何内容,但它确实允许您轻松编写非投掷交换(尽管使用C ++ 11移动语义时这不是一个问题)。

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

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM