2017-10-13 37 views
2

我有下面的代碼可以編譯(GCC7,C++ 17):如何強制執行模板,模板的模板參數之間的約束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影響另一個的錯誤。 OK還不錯,但在我的情況下,我想TTT一樣。我該如何執行?我想我可以以某種方式使用std::enable_ifstd::is_same?但在這種情況下,代碼會變得太多。有沒有更少的這種毛茸茸的解決方案?

  • 我幾乎看不到具有模板模板參數的代碼。我在做一些不被認爲是好的做法嗎?

  • 我不太喜歡這個解決方案的語法。有沒有更好的方法來做同樣的事情,但使用更簡潔/更簡單的代碼?

  • 雖然與模板模板參數的代碼是大丑,這是很明顯的,瞭解這些代碼做什麼:它只是允許用戶指定他/她自己的機制,爲NDArrayHost對象分配內存。只要不是很複雜一樣,如果你認爲我接近問題完全錯誤的,隨意點我一個更好的解決方案(Thrust

+1

「我想噸至與TT相同的」 這是沒有意義的。您的用戶爲NDArrayHost提供T. *您在NDArrayHost內部爲Alloc提供TT。如果你想TT與T相同,只需將T作爲Alloc的參數。 –

+0

TT是一個虛擬參數,寫入「template typename Alloc」具有相同的效果。此外,您不能將TT用於任何目的,基本上甚至可以使用模板 typename Alloc> class NDArrayHost { 使用UU = TT; };是非法的。 –

+0

問題是關於模板模板,與C++ 17標準無關。您可以編譯這個問題以及我在C++ 11中看到的答案。 –

回答

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