如何在C ++ 17

时间:2017-10-13 06:16:05

标签: c++ templates template-templates

我有以下编译代码(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影响另一个的错误。确定公平,但就我而言,我希望TTT相同。我该如何执行?我想我可以用某种方式使用std::enable_ifstd::is_same?但在这种情况下,代码将变得太毛茸茸。对此有什么不那么毛茸茸的解决方案吗?

  • 我几乎看不到带有模板模板参数的代码。我做的事情不是一种好的做法吗?

  • 我真的不喜欢这个解决方案的语法。是否有更好的方法来做同样的事情,但使用更简洁/更简单的代码?

  • 虽然带有模板模板参数的代码非常难看,但很明显要理解这段代码的用途:它只是允许用户指定他/她自己的机制来为NDArrayHost分配内存对象。虽然这符合一个完全不同/单独的问题:如果你认为我正在接近完全错误的问题,请随意指出一个更好的解决方案(只要不像Thrust那样复杂。

1 个答案:

答案 0 :(得分:4)

在途中是根据类型TAlloc声明基本模板,然后仅提供合法的部分专业化。

#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);
}
相关问题