偏特

2015-08-14 60 views
2

過程中使用非類型模板參數考慮以下struct S:偏特

//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轉換的三重int,doublestd::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版本類似的東西:

template <typename T> struct ArrayAs; 

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

我嘗試實例化時在叮噹(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標準,並且無法找到相關部分,而且我在解釋叮噹聲診斷消息時遇到了問題。

+3

您正在專注於功能類型。函數類型的形式爲'type(types ...)',沒有空間存放整數。換句話說,在任何情況下,B(double,2)語法在C++中都沒有意義。錯誤消息可以承認更有意義。 – Quentin

+0

你需要'2'作爲編譯時參數嗎? – sfjac

回答

2

當你專注TupleAs

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

你基本上是重載一個函數的符號。您正在專注於函數,它需要Args...並返回T。這是一種類型。你可能不會將該函數用作函數,或者真的把它看作是一個類型,但事實就是如此。

在另一方面,在這裏:

​​

有作爲需要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>) > 

,因爲現在我們又回到使用類型無處不在。無論你喜歡或不喜歡,都是個人喜好。

這裏的關鍵是,類型是所有事物模板元編程的頭等公民,在可能的情況下應避免使用值。

+0

不幸的是,'ArrayAs '不起作用。 – Yakk

+0

@Yakk'ArrayAs ''確實,但* yuck *。怪數列衰變:p – Quentin

+1

@Yakk我流下了眼淚 – Barry

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; 

live example

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

+0

我沒有想過嘗試使用數組下標的語法,謝謝。 – KyleKnoepfel