2016-03-28 6 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; 
} 

上記のコードはaの型としてstringを返す必要が何とかそれは常にint

答えて

7
TypeForIndex<2, int, double, string> 

OK、パターンマッチングの時間です。まず、明確に一致します。

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

ですのでエラーはありません。それは他の専門分野と一致しますか?

A:

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_indexHeadintTail...double, std::stringで、2あります。

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の定義を欠いています。

または、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、int型、ダブル、文字列> :: type'が' STRING'が修正ですとします。http://coliru.stacked-crooked。com/a/d2876707b8677e26 - 正しいタイプを返しますが、正しくありません。このリンクでは、パックの最後に 'char'型を追加して、コードをコンパイルできませんでした。 – Yakk

+1

はい。コンパイルするまでコードを編集していただけです。私は彼がさらに多くの間違いを抱えていることに気付かなかった。私は欠けている 'Tail ... 'をコードに追加しました。 – prestokeys

+0

@prestokeysあなたの答えをありがとう!あなたのものは私にとってちょうど意味がありましたが、私は先に進んでより良い説明があるので、ヤックの答えを受け入れるつもりです。私は15ポイントをあなたにupvoted! – Curious

関連する問題