带有模板类的pimpl习语是否有任何优势?

时间:2011-09-26 23:09:55

标签: c++ templates pimpl-idiom

我的理解是,pimpl习惯用法的主要好处是隐藏实现文件中的数据成员而不是标题。但是,模板需要在头文件中完全定义,以便编译器按需实例化它们。在这种情况下,对于模板化的类使用pimpl习语有什么好处吗?

5 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:1)

在大型项目中,单独解耦翻译单元是pimpl的充分理由。这甚至适用于模板:

// main interface

template <typename> struct MyImpl;

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

// implementation

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

// TheInterface implementation

答案 2 :(得分:1)

Theres有一个案例可能不是严格意义上的pimpl成语,但足够相似,值得了解。那就是在非类型安全版本上有一个类型安全模板包装器。

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_;
};

现在任何MyMap<T>的使用都不需要暴露给MapBase的内部,你只能获得这些函数的一个实现。我还考虑让MapBase成为一个抽象的基类,使解耦更加强大。

正如我所说,它不完全是一个pimpl,但它以类似的方式解决了同样的问题。

答案 3 :(得分:0)

我认为,如果你稍微扩展一些习惯用法,在某些情况下你至少可以得到一些。在模板中,并非每个操作都必须依赖于模板参数。所以你可以从Impl类继承,它本身使用了pimpl习语,如下所示:

struct FooPimpl;

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

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

当然,这在很大程度上取决于具体情况。但我看到pimpl习语在模板类上下文中工作。

答案 4 :(得分:0)

它仍然非常实用 - 考虑一个自动或共享指针,这是一个模板,非常适用于解决和实现PIMPL。它是否是最佳解决方案取决于问题。

  

模板需要在头文件中完全定义,以便编译器根据需要实例化它们。

你可以声明模板的成员和接口,然后在你的类型的cpp文件中,你可以#include必要的专业定义并在那里使用它们。