2010-11-20 16 views
5

Bazı kişiler here, bazılarının here öğesinin, bir şablonla yazılmış şablonun tüm farklı şablon argümanları için bir makine koduna sahip olabileceğini söyledi, bu yüzden bu özel konuyla ilgili bir iş parçacığı açmak için karlı olacağını düşündüm eğer böyle bir olasılık yoksa, eğer varsa, hangi durumlarda buna güvenebiliriz? özel olarak, her iki söz konuda kabul edildi bir örneği aşağıdaki gibidir:Şablonlu bir işlevin tüm şablon argümanları için bir makine kodu sürümüne sahip olma olasılığı var mı?

template<size_t num>  
struct Elements{ 
public: 
    SomeType elements[num]; 
}; 

template<size_t num> 
void print(const Elements<num> & elements,size_t size){ 
//all instances do exactly same thing and with regard to Size that determines the size of object 
} 

ve tabii ki aynı zamanda değer versiyonu ile geçiş vardır: bir akıllı bağlayıcı, iki farklı fonksiyon gövdesi aynı olduğunda tanıyabilir

template<size_t num> 
void print(const Elements<num> elements,size_t size){ 
//all instances do exactly same thing and with regard to Size that determines the size of object 
} 
+0

Değer-değer örneğinizde, farklı örneklerin birlikte katlanması imkansızdır, çünkü elemanlar parametresinin boyutu farklı olabilir. Bu da, prolog/epilog işlevini (yığının ayrıldığı ve daha sonra temizlendiği) etkileyecektir. – Crashworks

+0

@Crashworks_So yığın ayırma, her işlev çağrısı başına farklı boyutlarda yığın çerçevesi ayırma işini yapamaz mı? – Pooria

+0

Hata ayıklayıcınızın sökme penceresindeki birkaç işlev çağrısına bakmayı ve yığının gerçekte nasıl ayrıldığını görmeyi denemelisiniz. Bu küçük kutuya sığabilecek her şeyden daha aydınlatıcı olabilir. =) – Crashworks

cevap

5

ve bunları bir sembol haline getirin. Bu, MSVC'de "COMDAT katlama" ve diğer birçok yerde "çift sıyırma" olarak adlandırılır. Örneğin, aşağıdaki iki işlev, farklı türler almasına rağmen, PPC üzerinde aynı şekilde derlenebilir: çünkü türler aynı boyuttadır ve verilen durumda aynı şekilde davranırlar.

template<typename T> 
GetLowBit(T foo) { return T & 1; } 

GetLowBit<unsigned long>(ulong x); // compiles to "li r4, 1 ; and r3, r3, r4 ; blr " 
GetLowBit<signed long>(long x); // also compiles to "li r4, 1 ; and r3, r3, r4 ; blr " 

ve GetLowBit<unsigned long> çağrısı GetLowBit<signed long> bir çağrı ile aynı adrese gider böylece, olduğu gibi o kadar bağlayıcı, aynı yere kendi "isimleri" noktasının her iki yapabilirsiniz. Bu nedenle, genel olarak, hepsi aynı tür boyutlarda aynı işlevlerde çalışan farklı şablon örneklerini bir araya getirmek mümkündür. (Özellikle, işaretçileri veya çeteleler saklamak konteynerler üst üste katlanarak almak eğilimindedirler.)

Bu sadece şablon işlevleri için olmaz. Bazı bağlayıcılar, herhangi iki fonksiyonun aynı cisimlere sahip olduğunu ve bunları birleştirdiğini fark edebilir. Özellikle ben MSVC hiçbir şey yapmaz her sanal fonksiyonunu daraltmak ama (başka bir şey ayıklarken Çözücü olarak) sık sık bakın

class A 
{ 
    virtual void nothing() {}; 
} 

class B 
{ 
    virtual void empty() {}; 
} 

için bir uber-fonksiyonu, örneğin içine dönmek eğiliminde olduğunu görüyoruz nothing için vtable girişleri ve empty her ikisi de aynı işlev gövdesini işaret eder, bu da sadece ret'dur. Bu konuda

güvenebilir miyim? Hayır Bu onları fark ettiğinde akıllı bağlayıcı fonksiyonları için sağlayabilir bir özelliktir. Bağlantınız aptal olabilir — Orada bir sürü berbat derleyici var. Yalnızca belirli komut argümanlarını tedarik ederseniz olabilir. Bazı işlevler için gerçekleşebilir, ancak yalnızca linker tarafından bilinen nedenlerden ötürü değil. Hatta programda başka ne olduğuna bağlı olarak inşatan farklı olabilir.

Genel olarak, evet, bu , olabilir ve ne zaman olursa, çalıştırılabilir boyutta güzel bir tasarruf olabilir. Ancak, linker'ınıza ve tüm özelliklerine aşina olmadığınız sürece buna güvenemeyebilirsiniz.

0

Çoğu normal şablon için bu mümkün değildir. Şablonların kullanılmasının nedeni, her biri için ayrı makine koduna ihtiyacınız olmasıdır. Spesifik örneğinizde, derleyici aslında, kesinlikle katlanamayan farklı tipler yaratıyor ve değer-değer senaryosunda (ki bu arada çılgın oluyor), ne kadar alanın alacağını bilmek gerekiyor. yukarı.

0

Kendi sorgunuzla ilgili olarak: Şablon bağımsız değişkenine göre çoğu fonksiyonun ayırt edilmediği bir şablon sınıfına ihtiyacım varsa, genellikle şablon olmayan bir temel sınıf yapıyorum. Bu, yöntemlerin çoğunun bir başlık yerine .cc dosyasına taşınmasına ve işlev kopyalarının beklenmedik şekilde çoğalmamasına izin verir.

Daha genel: Eğer (senin size_t num güzel bir örneğidir) nedeniyle parametreye şablonunuzun birçok uzman örneklerini sebep olabileceğini hiç kendinizi endişeli bulursanız muhtemelen gerçekten bir yapıcı olması gereken bir şablon parametresi keşfettim parametresi.

+0

Bu durumda, bir derleme zamanı sabiti olması gerektiğinden, bir yapıcı parametresi olamaz. – UncleBens

+0

Eğer 'SomeType elements [num] 'nedeniyle," SomeType * elements "ve dinamik ayırmaya gitmekten vazgeçtiğinizi söylüyorsanız? Sonuçta, 'std :: vector', bir şablon parametresi olarak boyut almadan çok dizi gibi davranmayı başarıyor. –

İlgili konular