c++ - 如何在 C++17 中强制模板和模板参数之间的约束

标签 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_if 和 std::is_same 吗?但在这种情况下,代码就会变得过于繁琐。有没有什么毛茸茸的解决方案?

  • 我几乎看不到带有模板模板参数的代码。我是否在做一些不被认为是良好做法的事情?

  • 我不太喜欢这个解决方案的语法。有没有更好的方法来做同样的事情,但代码更干净/更简单?

  • 虽然带有模板模板参数的代码非常丑陋,但是很明显可以理解这段代码的作用:它只是允许用户指定他/她自己的机制来为 NDArrayHost 对象。尽管这符合一个完全不同/单独的问题:如果您认为我完全错误地解决了这个问题,请随时向我指出更好的解决方案(只要不是像 Thrust 那样非常复杂。

最佳答案

一种方法是根据类型 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);
}

关于c++ - 如何在 C++17 中强制模板和模板参数之间的约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46723598/

相关文章:

c++ - C/pp 套接字,recv()/send() 仅在 gdb 下有效

c++ - 类初始化的 const 引用

c++ - 外线成员函数定义是否需要全局范围内的完全限定类名?

templates - 如何将Windows商店模板添加到Visual Studio 2013?

c++日志函数使用模板SFINAE进行条件编译

c++ - 使用 boost asio 时如何获取 UDP 远程端点?

c++ - dynamic_cast 中的模糊转换

c++ - 用户定义的模板约束只接受一个用户定义的模板类

c++ - 模板模板模板参数是扩展还是标准的一部分?

c++ - template 模板参数,算作一个单独的参数