Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ pimpl使模板编码不那么混乱_C++_Templates_Header - Fatal编程技术网

C++ pimpl使模板编码不那么混乱

C++ pimpl使模板编码不那么混乱,c++,templates,header,C++,Templates,Header,我试图创建一个更干净的头文件,用于头类的引用/文档,同时仍然认识到模板的方便性。所以我得到了一个快速的.h/.hpp文件 // mempool.h namespace internal { template<typename T,template<class> class Allocator> class MemoryPool; } template<typename T,template<class> class Allocator = st

我试图创建一个更干净的头文件,用于头类的引用/文档,同时仍然认识到模板的方便性。所以我得到了一个快速的.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); }
};
// 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
//mempool.h
命名空间内部{
模板
类内存池;
}
模板
类内存池
{
私有:内部::MemoryPool*pimpl;
public:MemoryPool();
public:virtual~MemoryPool();
public:void flush(){return pimpl->flush();}
public:T*find(T对象){return pimpl->find(对象);}
public:T*pop(){return pimpl->pop();}
public:void push(T对象){return pimpl->push(对象);}
};
又好又干净。 然后是一个.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); }
};
// 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
//mempool.hpp
#包括
#包括
名称空间cext{
名称空间内存{
#包括“memorypool.h”
模板
MemoryPool::MemoryPool()
:pimpl(新的内部::MemoryPool())
{
}
模板
MemoryPool::~MemoryPool()
{
删除pimpl;
}
命名空间内部{
模板
类内存池
{
私有:std::mutex mtx;
私有:分配器alloc;
public:MemoryPool()
:alloc()
{
//分配(256);
}  
public:~MemoryPool()
{
//alloc.deallocate();
}  
public:void flush()
{
mtx.lock();
看跌期权(“同花顺”);
mtx.unlock();
}
public:T*find(T对象)
{
mtx.lock();
看跌期权(“发现”);
mtx.unlock();
返回空ptr;
}
公众:T*pop()
{
mtx.lock();
看跌期权(“pop”);
mtx.unlock();
返回空ptr;
}
公共:无效推送(T对象)
{
mtx.lock();
卖出(“推”);
mtx.unlock();
}
};
}//结束内部
}//结束cext
}//结束存储器
所以我不认为使用pimpl对我有任何帮助,因为用户需要包含.hpp文件。若我并没有弄错的话,对实现的更改将导致链接器更新,所以并没有提高编译速度。考虑到我的情况,我可能会一起删除pimpl,包括.h文件和.hpp文件

问:我想知道是否有一种干净的方法可以像我在上面的.h文件中所做的那样显示模板的最小头,但仍然可以获得一些编译器的加速?如果有其他有效的方法,我不会选择pimpl


-干杯

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

然而,有一种有用的模板技术类似于我在类似场景中使用的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);
  }
};
名称空间内部{
类内存池
{
公众:
//分配最多“计数”块,其大小足以容纳“存储”中的“大小”
内存工具(std::size\u t size,std::size\u t count,void*存储);
void*allocate();//分配一个足以容纳“size”的块
void deallocate(void*p);//释放由“p”指向的块
};
}
模板
类MemoryPool:分配器,内部::MemoryPool
{
typedef分配器Alloc;
public:MemoryPool(std::size\u t n,const Alloc&a=Alloc())
:Alloc(a),internal::MemoryPool(sizeof(T),n,Alloc::allocate(n))
{
}
public:~MemoryPool();
public:T*poolNew(T对象)
{
T*p=static_cast(内部::MemoryPool::allocate());
Alloc::construct(p,object);
返回p;
}
公共:无效池删除(T*p)
{
Alloc::destroy(p);
返回内部::MemoryPool::解除分配(p);
}
};

这会产生理想的效果,允许
internal::MemoryPool
的实现隐藏在.cpp中。

看看如何在模板类中实现这一点。@John Zwinck谢谢,但这篇文章没有涉及到我的目的。@Cong Xu是的,我认为这个问题略有不同,因为用户正在尝试拆分模板文件的声明和定义。我的尝试是为模板类创建一个单独的接口类。我认为Willj已经了解了下面的内容,所以本质上是从内部类中去掉模板,对吗?我假设,如果类的外部部分已经被模板化,那么就没有真正的理由也模板化内部类。我将把Q打开一点,看看是否还有其他方法。谢谢你的回答很有帮助。