2016-03-28 10 views
4

Şablon meta programlamasını kullanarak bir parametre paketinde belirtilen dizinde tür almaya çalışıyorum. Aşağıda kodu var ama nedense her zaman bir int döndürür, birisi yanlış yaptığımı söyleyebilir mi?Şablon uzmanlıkları nasıl açılır

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

Yukarıdaki kod a için türü olarak string dönmelidir ama nedense hep bir int

cevap

7
TypeForIndex<2, int, double, string> 

Tamam, desen eşleştirme zamanıdır. İlk olarak,

hiçbir şekilde hatasız olarak eşleşir. Diğer uzmanlıklarla eşleşiyor mu?

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> 

Eh, (A) ve değil (B) ile eşleşir. (A) ile

, current_index Head int ve Tail... double, std::string olup, 2 olup.

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

Şimdi, private TypeForIndex<current_index + 1> oldukça işe yaramaz. Her zaman sadece boş bir bedene sahip birincil uzmanlık ile eşleşir ve özeldir, böylece kimse onu fark etmez. Programınızın davranışını hiç değiştirmeden kaldırabiliriz.

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

Yukarıda belirtildiği gibi, Headint olup. Böylece type=int elde ederiz.

Ve işte bu kadar. Bu nedenle type, int'dur.

...

Ne yanlış yapıyorsun neredeyse her şeydir? Derleme dışında (yani, imzayla eşleşen birincil uzmanlık var), sağladığınız kodun metninizde açıkladığınız şeyle alakası yoktur. Hatta current_index+1, metninizle ilgili açıklamalarda bulunmasını beklemeyeceğim bir dizedir.

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...> 
{}; 

ve bir çok geniş bir dizin geçirirseniz düzgün type için bir tanım yoksun:

birincil uzmanlık dışındaki herşeyi Fırlatma, bu çalışır.

int değil size_t kullanırım.

2

İşte düzeltmeniz.

#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

yukarıda ölçüde değiştirilmesi sadece bir düzeltmedir 'TypeForIndex <2, int çift, tel> :: type'' string' bir düzeltmedir ile http: //coliru.stacked-crooked.com/a/d2876707b8677e26 - doğru tür döndürür, ancak doğru değil. Bağlantıda, paketin sonuna bir "char" tipi ekledim ve kodunuz derlenemedi. – Yakk

+1

Evet. Kodunu derlenene kadar düzenlemekteydim. Daha da fazla hatalarının olduğunu anlamadım. Kayıp 'Tail ... 'koduna ekledim. – prestokeys

+0

@prestokeys Cevabınız için teşekkür ederiz! Seninki bana çok anlamlı geldi, ama daha iyi bir açıklaması olduğu için Yakk'un cevabını kabul edeceğim. 15 puanla seni reddettim! – Curious