我有以下编译代码(GCC7,C ++ 17):
template<typename T>
struct NDArrayHostAllocatorNew
{
static T* allocate(std::size_t size) {
return new T[size];
}
static void deallocate(const T* ptr){
delete [] ptr;
}
};
template<typename T, template<typename TT> typename Alloc>
class NDArrayHost
{
public:
typedef Alloc<T> allocator_type;
NDArrayHost(std::size_t size);
private:
T* m_data;
};
template<typename T, template<typename TT> typename Alloc>
NDArrayHost<T, Alloc>::NDArrayHost(std::size_t size)
{
m_data = allocator_type::allocate(size);
}
以下是我的问题:
如果我使用T
代替TT
,我会收到一个T
影响另一个的错误。确定公平,但就我而言,我希望T
与TT
相同。我该如何执行?我想我可以用某种方式使用std::enable_if
和std::is_same
?但在这种情况下,代码将变得太毛茸茸。对此有什么不那么毛茸茸的解决方案吗?
我几乎看不到带有模板模板参数的代码。我做的事情不是一种好的做法吗?
我真的不喜欢这个解决方案的语法。是否有更好的方法来做同样的事情,但使用更简洁/更简单的代码?
虽然带有模板模板参数的代码非常难看,但很明显要理解这段代码的用途:它只是允许用户指定他/她自己的机制来为NDArrayHost
分配内存对象。虽然这符合一个完全不同/单独的问题:如果你认为我正在接近完全错误的问题,请随意指出一个更好的解决方案(只要不像Thrust
那样复杂。
答案 0 :(得分:4)
在途中是根据类型T
和Alloc
声明基本模板,然后仅提供合法的部分专业化。
#include <cstddef>
#include <memory>
template<typename T>
struct NDArrayHostAllocatorNew
{
static T* allocate(std::size_t size) {
return new T[size];
}
static void deallocate(const T* ptr){
delete [] ptr;
}
};
/*
* declare the base template in terms of T and allocator
*/
template<typename T, typename Alloc>
class NDArrayHost;
/*
* only provide legal specialisations
*/
template<class T, template<class> class Alloc>
class NDArrayHost<T, Alloc<T>>
{
public:
typedef Alloc<T> allocator_type;
NDArrayHost(std::size_t size);
private:
T* m_data;
};
template<class T, template<class> class Alloc>
NDArrayHost<T, Alloc<T>>::NDArrayHost(std::size_t size)
{
m_data = allocator_type::allocate(size);
}
如果我们喜欢,我们可以添加专业化,以便在T不匹配时提供诊断:
/* specifically disallow illegal specialisations */
template<class T, class U, template<class> class Alloc>
class NDArrayHost<T, Alloc<U>>
{
static_assert(std::is_same<T, U>(), "meh");
};
...测试
int main()
{
NDArrayHost<int, NDArrayHostAllocatorNew<int>> h(10);
// fails with static assert
// NDArrayHost<int, NDArrayHostAllocatorNew<double>> h2(10);
}