2010-09-22 32 views
6

Hallo!C++ çoklu şablon parametreleri ile tek şablon uzmanlığı

İki şablon türünden yalnızca birini uzmanlaştırmak istiyorum. Örneğin. template <typename A, typename B> class X tek bir işlev için X<float, sometype>::someFunc() özel bir uygulama olmalıdır.

örnek kod:

main.h:

#include <iostream> 

template <typename F, typename I> 
class B 
{ 
public: 
    void someFunc() 
    { 
     std::cout << "normal" << std::endl; 
    }; 

    void someFuncNotSpecial() 
    { 
     std::cout << "normal" << std::endl; 
    }; 
}; 

template <typename I> 
void B<float, I>::someFunc(); 

main.cpp:

#include <iostream> 
#include "main.h" 

using namespace std; 

template <typename I> 
void B<float, I>::someFunc() 
{ 
    cout << "special" << endl; 
} 

int main(int argc, char *argv[]) 
{ 
    B<int, int> b1; 
    b1.someFunc(); 
    b1.someFuncNotSpecial(); 

    B<float, int> b2; 
    b2.someFunc(); 
    b2.someFuncNotSpecial(); 
} 

Derleme class B için başarısız olur. Bu doğru mu, C++ bu şekilde mümkün değil mi? En iyi çözüm ne olurdu? 26:

[değiştir]

template <float, typename I> void B<float, I>::someFunc(); main.h'da yol açar hatası: 27: float

template <typename I> void B<float, I>::someFunc(); main.h'da giden bir şablon sabit parametre için geçerli bir tür değildir: hata: eksik 'tip B' türü geçersiz kullanımı '

Ve gcc kullanıyorum.

[değiştir] Bir ihtisas olmayan diğer işlevleri gibi, bütün sınıfı uzmanlaşmak istemiyoruz

. Ayrıca, sadece uzmanlık içinde someFunc tanımlayabilir

template <typename I> 
class B<float, I> 
{ 
public: 
    void someFunc(); 
}; 

template <typename I> 
void B<float, I>::someFunc() 
{ 
    ... 
} 

:

+0

Sınıf şablonu A sorunuzla ilgili mi? – Doug

+0

Sorunun anlaşılmasını kolaylaştıracağını düşündüm. Onu kaldıracağım. – tauran

+0

Bu, stackoverflow'ta yüzlerce kez soruldu. :) Bazılarımızın bu gibi sorularla gerçek bir şablon SSS oluşturabileceğini düşünüyorum. Kişiler soru sorulup cevaplanmadığını görmek için SSS'yi kontrol edebilirler. –

cevap

16

class şablon B bir kısmi uzmanlık sağlamak gerekir. Yalnızca bir işlevi uzmanlaştırmak istiyorsanız ve bir sınıfın yapmasını istemiyorsanız, Ancak, Ancak, bir işlevi uzmanlaştırmak istiyorsanız, e. g.

template <typename F, typename I> 
void someFunc(F f, I i) { someFuncImpl::act(f, i); } 

template <typename F, typename I> 
struct someFuncImpl { static void act(F f, I i) { ... } }; 

// Partial specialization 
template <typename I> 
struct someFuncImpl<float, I> { static void act(float f, I i) { ... } }; 

Ancak bu numara olmadan bir işlev şablonunu uzmanlaştıramazsınız.

+1

Bunu bilmiyordunuz. Ama benim kullanımımda bir uzmanlığa sahip olmayan birçok başka fonksiyon var. Bu yaklaşımla tüm bu fonksiyonları ikiye katlamak zorunda kalacağım. – tauran

+1

@tauran: İşlev şablonları için kısmi uzmanlık sağlayamıyorsunuz. Sadece sınıf şablonları için ve tanımlamayı bütün sınıf için tekrar sağlamanız gerekir. Onunla yaşamak veya güncellenmiş cevabı görmek. –

+0

Tauran kodunda bir şey daha ele alabilir misiniz? "Main.h" öğesinin sonunda geçersiz B :: someFunc(); Sanırım tauran, başka bir derleme biriminde bir yerde tanımlanmış bir uzmanlık olduğunu beyan etmek istiyor. Böyle bir şey dışa aktarılmış şablon gerektirmiyor mu? Eğer uzmanlaşma kastediliyorsa, tüm derleme birimlerinde görünmek için, 'main.h', başlığa dahil edilmek zorunda değil mi? –

5

Although you can totally specialize member functions of a class template, you cannot _partially specialize member functions. - Andrei Alexandrescu

kısmi Sınıf uzmanlık diğer afiş ile açıklanmaktadır.

Ancak, kullanım aşırı edebilirsiniz:

template <class T, class U> T fun(U obj); // primary template 
template <class U> void Fun<void, U>(U obj); // illegal pertial 
// specialization 
template <class T> T fun (Window obj); // legal (overloading) 

derin bu işe, A. Alexandrescu'nun "Modern C++ Tasarım" derinlemesine bu konuda okuyabilir gitmek istiyorum.

+0

+1 özel sürümü görmezden olur. Bu, kullanımı hakkında nadiren düşündüğüm, ancak bazı durumlarda işi yapan bir araçtır. –

0

Çözüm 1. tüm uygulamaları B_Base gibi bir temel sınıfa taşıyın. sonra bazıFunc geçersiz kılmak için şamandıra üzerinde uzmanlaşmak. Çözüm

template <typename F, typename I> 
    class B : B_Base<F, I> 
    { 
    } 

    template <typename I> 
    class B<float, I> : B_Base<flat, I> 
    { 
    public: 
     void someFunc() {....} 
    }; 

altında 2. kullanım fonksiyonu aşırı gibi, girdi olarak şamandıra koymak veya artırmak :: is_same merkeze.ne yazık ki, işlevinde bazıFunc parametresinde yok. bu yüzden arayüzü değiştirmek gerekiyor.

İlgili konular