0

I'm attempting to create a cleaner header file for reference/documentation of header classes while still recognizing the convenience of templates. So I've got a quick .h / .hpp file

// 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); }
};

Nice and clean. Then a .hpp file

// 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

So I don't think using pimpl did anything for me since users would need to #include the .hpp file. Changes to implementation would cause linker updates so no compile speed boost, if I'm not mistaken. I could probably do away with the pimpl all together given how I am #including the .h file in the .hpp file.

Q: I'd like to know if there is a clean way to display a minimal header for a template as I've done above in the .h file, but still get some compiler speed-up's? I'm not set on pimpl if there are other methodologies that work.

-Cheers

4

1 に答える 1

0

不明な型のセットに対してテンプレートの暗黙的なインスタンス化をサポートする必要がある場合は、テンプレートの実装をコンパイラから見えるようにする必要があります。

ただし、同様のシナリオで使用した 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 に隠すことができるという望ましい効果が得られます。

于 2013-06-11T11:42:49.927 に答える