簡體   English   中英

在部分專業化期間使用非類型模板參數

[英]Using non-type template argument during partial specialization

考慮以下struct

//Implementations provided elsewhere

struct A {  A(int i, double d, std::string s);  /* ... */ };
struct B {  B(double d1, double d2);            /* ... */ };

我有兩個轉換類,其模板簽名如下:

TupleAs< A, int, double, std::string > via1 { ... };
ArrayAs< B, double, 2 >                via2 { ... };

可以預見, TupleAs會將intdoublestd::string值的三元組轉換為A類型的對象。 同樣, ArrayAs將兩個兩個double值對轉換為B類型的對象。 (是的,有一些原因導致我不能直接調用AB構造函數。)

改善語法

我想更改語法,以便可以執行以下操作:

TupleAs< A(int,double,std::string) > via1 { ... };
ArrayAs< B(double,2) >               via2 { ... };

我認為這更能描述轉換過程。 TupleAs模板聲明和相應的部分專業化如下所示:

template <typename T> struct TupleAs;

template <typename T, typename ... Args>
struct TupleAs<T(Args...)> { ... };

編譯錯誤

但是,如果我嘗試對ArrayAs版本執行類似ArrayAs

template <typename T> struct ArrayAs;

template <typename T, typename U, unsigned N>
struct ArrayAs<T(U,N)> { ... };

嘗試實例化它時,在clang(3.6)中出現以下錯誤( ArrayAs< B(double,2)> test; ):

typeAs.cpp:14:22: error: unknown type name 'N'
  struct ArrayAs<T(U,N)>{
                     ^
typeAs.cpp:14:10: warning: class template partial specialization contains a template parameter that cannot be deduced; this partial specialization will never be used
  struct ArrayAs<T(U,N)>{
         ^~~~~~~~~~~~~~~
typeAs.cpp:13:45: note: non-deducible template parameter 'N'
  template<typename T, typename U, unsigned N>
                                            ^

gcc錯誤診斷有些不同,但是我不會在這里發布。

我承認我的模板技術應該比他們更好,並且我也承認類似的std::function<B(double,2)>聲明顯然是胡說八道。 但是有人可以告訴我為什么不允許我嘗試實現的特定語法嗎? 我瀏覽了C ++ 14標准,找不到相關部分,並且在解釋clang診斷消息時遇到了麻煩。

當您專門研究TupleAs

template <typename T, typename ... Args>
struct TupleAs<T(Args...)>

您基本上是在重載函數的符號。 您正在專門研究采用Args...並返回T函數 那是一種類型。 您可能沒有將該函數用作函數,或者甚至從未將其視為類型,但這就是它的本質。

另一方面,在這里:

template <typename T, typename U, unsigned N>
struct ArrayAs<T(U,N)> { ... };

函數不存在需要N 它可以是unsigned ,但不能是一個 只是沒有這種合理的事情。 從您的示例來看, B(double, 2)根本沒有道理。 充其量,您可以編寫允許以下內容的內容:

template <unsigned N> using size_ = std::integral_constant<size_t, N>;

ArrayAs< B(double,size_<2>) >

甚至:

ArrayAs< B(std::array<double, 2>) >

從現在開始,我們回到了在所有地方使用類型的地方。 個人喜好是否喜歡。

這里的關鍵是,在涉及模板元編程的所有事情時,類型是一等公民,應盡可能避免使用值。

template <typename T> struct ArrayAs;

template <typename T, typename U, std::size_t N>
struct ArrayAs<T(std::array<U,N>)> { ... };

工作原理如下:

template<class T>
struct to_array;
template<class T, size_t N>
struct to_array< T[N] > { using type = std::array<T, N>; };
template<class T>
using arr = typename to_array<T>::type;

然后:

ArrayAs< Bob( arr<int[3]> ) > some_var;

現場例子

可悲的是,由於函數類型中的數組如何衰減到指針,直接使用ArrayAs< Bob( int[3] ) >不起作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM