【问题标题】:pimpl to make template coding less clutteredpimpl 使模板编码不那么混乱
【发布时间】:2013-06-11 07:13:50
【问题描述】:

我正在尝试创建一个更简洁的头文件,用于头类的参考/文档,同时仍然认识到模板的便利性。所以我有一个快速的 .h / .hpp 文件

// mempool.h
namespace internal {
  template<typename T,template<class> class Allocator>
  class MemoryPool;
}

template<typename T,template<class> class Allocator = std::allocator>
class MemoryPool
{
  private: internal::MemoryPool<T,Allocator> *pimpl;

  public: MemoryPool();
  public: virtual ~MemoryPool();

  public: void  flush()        { return pimpl->flush();      }
  public: T    *find(T object) { return pimpl->find(object); }
  public: T    *pop()          { return pimpl->pop();        }
  public: void  push(T object) { return pimpl->push(object); }
};

干净整洁。 然后是一个 .hpp 文件

// mempool.hpp
#include <memory>
#include <mutex>

namespace cext {
namespace memory {
#include "memorypool.h"

template<typename T,template<class> class Allocator>
MemoryPool<T,Allocator>::MemoryPool()
:pimpl(new internal::MemoryPool<T,Allocator>())
{

}

template<typename T,template<class> class Allocator>
MemoryPool<T,Allocator>::~MemoryPool()
{
  delete pimpl;
}

namespace internal {

template<typename T,template<class> class Allocator = std::allocator>
class MemoryPool
{
  private: std::mutex mtx;
  private: Allocator<T> alloc;

  public: MemoryPool()
  :alloc()
  {
  //alloc.allocate(256); 
  }  

  public: ~MemoryPool()
  {
  //alloc.deallocate();  
  }  

  public: void flush()
  {
    mtx.lock();

    puts("flush");

    mtx.unlock();
  }
  public: T *find(T object)
  {
    mtx.lock();

    puts("find");

    mtx.unlock();
    return nullptr;
  }
  public: T *pop()
  {
    mtx.lock();

    puts("pop");

    mtx.unlock();
    return nullptr;
  }

  public: void push(T object)
  {
    mtx.lock();

    puts("push");

    mtx.unlock();
  }
};

} // end internal
} // end cext
} // end memory

所以我认为使用 pimpl 对我没有任何帮助,因为用户需要#include .hpp 文件。如果我没记错的话,对实现的更改会导致链接器更新,因此不会提高编译速度。考虑到我是如何在 .hpp 文件中包含 .h 文件的方式,我可能可以一起取消 pimpl。

问:我想知道是否有一种简洁的方法来显示模板的最小标头,就像我在上面在 .h 文件中所做的那样,但仍然可以获得一些编译器加速?如果还有其他可行的方法,我就不会使用 pimpl。

-干杯

【问题讨论】:

标签: c++ templates header


【解决方案1】:

如果您需要为未知类型集支持模板的隐式实例化,则必须使模板的实现对编译器可见。

但是,我在类似场景中使用过一种类似于 pimpl 的有用模板技术。这涉及将不依赖于模板参数类型的模板的实现“提升”到单独的类中。这是一个基于您的问题的示例 - 稍作修改以匹配我实现池分配器的方式:

namespace internal {

  class MemoryPool
  {
    public:
    // allocates up to 'count' blocks big enough to hold 'size' from 'storage'
    MemoryPool(std::size_t size, std::size_t count, void* storage);
    void* allocate(); // allocates a block big enough to hold 'size'
    void deallocate(void* p); // deallocates the block pointed at by 'p'
  };
}

template<typename T,template<class> class Allocator = std::allocator>
class MemoryPool : Allocator<T>, internal::MemoryPool
{
  typedef Allocator<T> Alloc;

  public: MemoryPool(std::size_t n, const Alloc& a = Alloc())
    : Alloc(a), internal::MemoryPool(sizeof(T), n, Alloc::allocate(n))
  {
  }
  public: ~MemoryPool();

  public: T    *poolNew(T object)
  {
    T* p = static_cast<T*>(internal::MemoryPool::allocate());
    Alloc::construct(p, object);
    return p;
  }
  public: void  poolDelete(T* p)
  {
    Alloc::destroy(p);
    return internal::MemoryPool::deallocate(p);
  }
};

这具有允许internal::MemoryPool 的实现隐藏在.cpp 中的预期效果。

【讨论】:

  • 所以本质上是从内部类中取出模板对吧?而且我认为鉴于类的外部部分已经模板化,没有真正的理由也模板化内部类。我将把 Q 留得更久,看看是否还有其他方法。谢谢你的回答很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-21
  • 1970-01-01
  • 2012-07-06
相关资源
最近更新 更多