2010-07-30 22 views
40

Olası çoğaltmaları: Bu kodunun nasıl
Can someone explain this template code that gives me the size of an array?
Magic arguments in function templates…Bu "dizi boyut" şablon işlevi nasıl çalışır?

Birisi açıklayabilir misiniz? Bu kodun amacı bir dizi uzunluğunu elde etmek olduğunu biliyoruz, ama bu kod nasıl çalıştığını bilmiyorum:

template<typename T, int size> 
int GetArrLength(T(&)[size]){return size;} 

teşekkür ederiz.

+0

Herhangi bir boyut göremiyorum ... –

+5

@thyrgle: bu," sizeof "e göre avantajlıdır. yanlışlıkla bir dizi yerine bir işaretçi verirseniz, derleme başarısız olur. –

+1

Yine başka bir yinelenen. Gerçekten tüm dupes'lerle ilgili bir sorun var: http://stackoverflow.com/questions/437150/can-someone- açıklamak-bu-şablon-kodu-bu-bana-bir-boyut-of-bir-dizisi verir (bunun için birkaç çiftleri vardır) Ben bunları bulup işaretleyen tek kişi olduğumu merak ediyorum. Bu oylar, 4 oy ile, bu şekilde işaretlediğim diğer sorularda bulduğum gibi, neredeyse hiç kapanmadı. Daha yüksek itibara sahip insanların oyları, diğer insanlardan çok daha fazla oy vermelidir.Bu şekilde, sorular daha hızlı bir şekilde kapatılabilir –

cevap

50

İlk önce, T(&)[size] parametreyi teşrih edelim. İçten dışa, sağdan sola, parantez grubu ilk bildirimlerini okuyun: Bu,türünde T türünde bir dizi referansı olan adlandırılmamış bir parametredir. olduğu

, bu dizi tipi ve boyutu şablon parametrelerdir bir dizi, bir referans kabul eder.

biz de buna çağırırsanız:

int a[10]; 
GetArrLength(a); 

derleyici şablon parametrelerini anlamak çalışacaktır. Parametre türü geçirerek şeyi eşleşmesi için, Tint olmalı ve size 10 (parametre 10 int s bir dizi için bir referans yapma) olması gerekir.

Sonra size bir dizideki öğe sayısını veren bu boyutu dönmek

.


Bu kodla ilgili iki "sorun" var. Öncelikle, boyutlar negatif olamaz, bu nedenle şablon parametresi ve dönüş türü olarak işaretli bir tür kullanmak mantıklı değildir. Daha ziyade, imzasız bir tür kullanılmalıdır; En iyi std::size_t olacaktır:

template<typename T, std::size_t Size> 
std::size_t GetArrLength(T(&)[Size]) { return size; } 

ikinci Bu fonksiyonun sonucu, dizinin büyüklüğü olsa da, sabit bir ifade olmadığıdır. Bu çoğu durumda iyi olsa da, ondan sabit bir ifade elde edersek daha iyi olurdu.

template <std::size_t N> 
struct type_of_size 
{ 
    typedef char type[N]; 
}; 

template <typename T, std::size_t Size> 
typename type_of_size<Size>::type& sizeof_array_helper(T(&)[Size]); 

#define sizeof_array(pArray) sizeof(sizeof_array_helper(pArray)) 

Bu gibi kullanılır:

Bu üç şey çalışır
int a[10]; 
const std::size_t n = sizeof_array(a); // constant-expression! 

: öncelikle yukarıda belirtilen fikir, o şablon parametreleri dolu olacak Yani bu çözüm ile sona nerede dizinin büyüklüğünü vermek.

ikinci parça

belirli bir boyutu olan bir tipi, bu nedenle type_of_size yardımcı olmak için bu bilgileri kullanmaktadır. Bu bölüm kesinlikle gerekli değil, ama kodun okunmasını daha kolay hale getirdiğini düşünüyorum. Bir char[N] bir N eşit büyüklüğü, her zaman, dolayısıyla biz tip kendisinin boyutu dizinin ... boyutuna "store" o kötüye kullanabilirler var!

üçüncü kısım sizeof ile bu boyutu oluyor. Aslında hiçbir şeyi değerlendirmiyor, bu yüzden fonksiyon için bir tanımlamaya ihtiyacımız yok. Basitçe "Eğer bunu yapsaydın ..." derboyutu ... ". Ve boyutu char dizisi içinde" depolanan "boyutudur.

+0

fakat kodu T & [size] olarak değiştirirsem işe yaramaz, neden? (&) ile yalnızca & arasındaki fark nedir? – BobAlmond

+5

T & [size] bir dizi referanstır. Bir diziye referans vermek istersiniz. –

+0

@Bob: Bildirimlerle ilgisi var. Kafan karışmış olabilir çünkü bunun için bir isim yok, orada bir tane yapışmayı deneyin. T (& x) [N] x ile bir N T dizisine başvurulur. Ancak: 'T & x [N] 'x, T.'ye yapılan bir N referansı dizisidir (Hangi yasa dışıdır.) İlk olarak içten dışa, sağdan sola, parantez içindeki bildirimleri okuyun. – GManNickG