2009-10-01 23 views
23

Şablon sınıfının belirli üyelerini uzmanlaşmak mümkün müdür? Bir şey gibi: bu kod geçerli değil. Bu benim ile geldi budurBelirli üyelerin şablon uzmanlığı?

+0

Burada ne demek istediğiniz tamamen açık değildir. Şablon parametresini belirli bir türün torunu olmak için zorlamak mı istiyorsunuz? ile Java'da yapabilirsiniz? –

+1

@Alcon Bir şablon sınıfında uzmanlaşırken, tüm sınıf için * farklı * uygulama sağlamalıdır. Bana öyle geliyor ki, birkaç fonksiyon dışında uzmanlıklar arasında ortak kod paylaşmak istiyor. – AraK

+0

Bu soru "üye" yerine "üye işlev" deyin mi? Kimsenin bunun veri üyeleri hakkında olduğunu düşünmemesi için. –

cevap

3

, yalnızca tüm şablon argümanları sunarak bunu açıkça uzmanlaşabilir :)

//The generic template is by default 'flag == false' 
template <class Type, bool flag> 
struct something 
{ 
    void doSomething() 
    { 
     std::cout << "something. flag == false"; 
    } 
}; 

template <class Type> 
struct something<Type, true> : public something<Type, false> 
{ 
    void doSomething() // override original dosomething! 
    { 
     std::cout << "something. flag == true"; 
    } 
}; 

int main() 
{ 
    something<int, false> falseSomething; 
    something<int, true> trueSomething; 

    falseSomething.doSomething(); 
    trueSomething.doSomething(); 
} 
+5

Geçersiz kılmıyorsunuz, sadece saklanıyorsunuz. – curiousguy

26

kadar kötü değil. Sınıf şablonlarının üye işlevleri için kısmi uzmanlığa izin verilmez.

template <typename T,bool B> 
struct X 
{ 
    void Specialized(); 
}; 

// works 
template <> 
void X<int,true>::Specialized() 
{ 
    ... 
} 

etrafında bir eser hala aynı sınıfta olmanın yararı vardır ve bu yüzden üye değişkenler, fonksiyonlar aynı erişim ve

// "maps" a bool value to a struct type 
template<bool B> struct i2t { }; 

template <typename T,bool B> 
struct X 
{ 
    void Specialized() { SpecializedImpl(i2t<B>()); } 

private: 
    void SpecializedImpl(i2t<true>) { 
     // ... 
    } 

    void SpecializedImpl(i2t<false>) { 
     // ... 
    } 
}; 

Not maddeleri aşırı yüklü işlevleri tanıtmak olduğunu aşırı yüklenen fonksiyonlara geçerek ve şablon parametrelerini bir fonksiyon parametresine bastırarak, fonksiyonlarınızı keyfi olarak "özelleştirebilir" ve aynı zamanda bunları gerektiği şekilde düzenleyebiliriz. Başkaları sınıf şablonu şekilde riayet tercih ederken diğer yaygın teknik,

template<typename T, bool B> 
struct SpecializedImpl; 

template<typename T> 
struct SpecializedImpl<T, true> { 
    static void call() { 
    // ... 
    } 
}; 

template<typename T> 
struct SpecializedImpl<T, false> { 
    static void call() { 
    // ... 
    } 
}; 

template <typename T,bool B> 
struct X 
{ 
    void Specialized() { SpecializedImpl<T, B>::call(); } 
}; 

zaman daha çok kod gerektirir bulmak ve ben işlevi işlemek için daha kolay aşırı bulmak ayrı ayrı tanımlanmış bir sınıf şablonuna erteleme etmektir. Sonunda bir tat meselesi. Bu durumda, X içine başka bir şablonu da iç içe bir şablon olarak yerleştirebilirdiniz - diğer durumlarda sadece kısmen değil, açıkça uzmanlaştığınız durumda, bunu yapamazsınız, çünkü açık uzmanlıkları yalnızca ad alanı kapsamına yerleştirebilirsiniz. sınıf kapsamına değil. Aşağıdaki varyant çok ilk parametre değişkeni bırakır gösterdiği gibi

Ayrıca sadece aşırı işlevin amacı doğrultusunda böyle bir SpecializedImpl şablon oluşturabilir, (o zaman önce bizim i2t benzer çalışır) (böylece diğer çağırabilir türleri - sadece şimdiki instantiation şablon parametreleri ile)

template <typename T,bool B> 
struct X 
{ 
private: 
    // maps a type and non-type parameter to a struct type 
    template<typename T, bool B> 
    struct SpecializedImpl { }; 

public: 
    void Specialized() { Specialized(SpecializedImpl<T, B>()); } 

private: 
    template<typename U> 
    void Specialized(SpecializedImpl<U, true>) { 
     // ... 
    } 

    template<typename U> 
    void Specialized(SpecializedImpl<U, false>) { 
     // ... 
    } 
}; 

başka şablonu (daha da ertelenmesi, bazen düşünüyorum elinden zor aşırı ve sadece sınıf şablonuna yönlendirme, diziler ve işaretçiler gibi durumlarda söz konusu olduğunda o zaman benim için daha kolay oldu, ve bazen sadece şablon içinde aşırı yükleme daha iyi - özellikle eğer gerçekten işlev argümanları koyar ve sınıfların üye değişkenlerine dokunursanız.

+0

+1 Gözlerimin önünde güzel ve zarif çözümler. – AraK

+0

teşekkürler, minnettarım :) –

+0

Şimdi bu C++ 11 çıktı, bunun yerine “std :: integral_constant” ın kullanılması gerektiğini düşünüyor. Kendimi düzenlerdim, ancak iPod Touch'taki mobil görünümde gerçek bir güçlük var ... – Xeo

İlgili konular