2016-03-28 90 views
4

我想使用模板元編程在參數包中的指定索引處獲取類型。我有下面的代碼,但由於某種原因它總是返回一個int,有人可以告訴我我做錯了什麼嗎?如何展開模板專門化

#include <string> 
#include <iostream> 
using std::cout; 
using std::endl; 
using std::string; 

template <int current_index, typename... Vs> 
struct TypeForIndex {}; 
template <int current_index, typename Head, typename... Tail> 
struct TypeForIndex<current_index, Head, Tail...> : private TypeForIndex<current_index + 1> { 
    using type = Head; 
}; 
template <int current_index, typename Tail> 
struct TypeForIndex<current_index, Tail> { 
    using type = Tail; 
}; 

int main() { 

    TypeForIndex <2, int, double, string>::type a {"hello"}; 
    cout << a << endl; 

    return 0; 
} 

上述代碼應返回string作爲a的類型,但不知它始終是一個int

回答

7
TypeForIndex<2, int, double, string> 

確定,模式匹配時間。首先,它明顯匹配

template <int current_index, typename... Vs> 
struct TypeForIndex {}; 

所以沒有錯誤。它是否與任何其他專業匹配?

答:

template <int current_index, typename Head, typename... Tail> 
struct TypeForIndex<current_index, Head, Tail...> 

B:

template <int current_index, typename Tail> 
struct TypeForIndex<current_index, Tail> 

好了,它匹配(A),而不是(B)。

與(A),是current_index2HeadintTail...double, std::string

template <int current_index, typename Head, typename... Tail> 
struct TypeForIndex<current_index, Head, Tail...> : private TypeForIndex<current_index + 1> { 
    using type = Head; 
}; 

現在,private TypeForIndex<current_index + 1>幾乎沒用。它總是隻匹配主體,它有一個空的主體,它是私人的,所以沒有人會注意到它。我們可以在不改變程序行爲的情況下將其刪除。

template <int current_index, typename Head, typename... Tail> 
struct TypeForIndex<current_index, Head, Tail...> { 
    using type = Head; 
}; 

如上所述,Headint。所以我們得到type=int

就是這樣。這就是爲什麼typeint

...

你在做什麼錯誤幾乎是一切?除編譯外(即主要專業化與簽名匹配),您提供的代碼與您在文本中描述的內容無關。即使current_index+1是一個字符串,我不希望存在於執行你的文本描述的代碼中。

踢出以外的所有主要專業化,這個工程:

template <typename Head, typename... Tail> 
struct TypeForIndex<0, Head, Tail...> { 
    using type = Head; 
}; 
template <int current_index, typename Head, typename... Tail> 
struct TypeForIndex<current_index, Head, Tail...>: 
    TypeForIndex<current_index-1, Tail...> 
{}; 

,如果你通過一個過大的指數得當缺少type的定義。我也會用size_t而不是int

2

這是您的修復程序。

#include <string> 
#include <iostream> 
using std::cout; 
using std::endl; 
using std::string; 

template <int current_index, typename... Vs> 
struct TypeForIndex {}; 

template <int current_index, typename Head, typename... Tail> 
struct TypeForIndex<current_index, Head, Tail...> : TypeForIndex<current_index - 1, Tail...> {}; 

template <typename Head, typename... Tail> 
struct TypeForIndex<0, Head, Tail...> { 
    using type = Head; 
}; 

int main() { 
    TypeForIndex <2, int, double, string, char>::type a ("hello"); 
    cout << a << endl; 
} 
+0

上面的僅僅是一個固定,只要更換'TypeForIndex <2,整型,雙,字符串> :: type'用'string'是一個修正:HTTP://coliru.stacked-crooked。com/a/d2876707b8677e26 - 它返回正確的類型,但不正確。在鏈接中,我在包的最後添加了一個'char'類型,並且代碼無法編譯。 – Yakk

+1

是的。我編輯他的代碼直到編譯完成。我沒有意識到他犯了更多的錯誤。我在代碼中添加了缺少的「尾部...」。 – prestokeys

+0

@prestokeys謝謝你的回答!你的意見對我來說同樣重要,但我會繼續接受Yakk的回答,因爲它有更好的解釋。雖然我贊成15分! – Curious