2009-12-14 26 views
7

Ho una classe di modelli A < T, int> e due typedefs A < string, 20> e A < string, 30>. Come sovrascrivere il costruttore per A < stringa, 20>? Quanto segue non funziona:Specializzazione template C++ del costruttore

template <typename T, int M> class A; 
typedef A<std::string, 20> one_type; 
typedef A<std::string, 30> second_type; 


template <typename T, int M> 
class A { 
public: 
    A(int m) {test= (m>M);} 

    bool test; 

}; 


template<> 
one_type::one_type() { cerr << "One type" << endl;} 

Vorrei che la classe A < std :: string, 20> di fare qualcosa che l'altra classe non lo fa. Come posso fare questo senza cambiare il costruttore A: A (int)?

+0

Cosa stai cercando di ottenere le classi di fare? – GManNickG

+0

La domanda non è chiara. A proposito, one_type non ha costruttore vuoto, ha costruttore con parametro int. – Drakosha

risposta

1

Non è possibile con il vostro approccio attuale. one_type è un alias per una particolare specializzazione template, quindi ottiene qualunque codice abbia il template.

Se si desidera aggiungere codice specifico per one_type, si deve dichiarare come una sottoclasse di una specializzazione, in questo modo:

class one_type: 
    public A<std::string>, 20> 
    { 
    one_type(int m) 
     : A<str::string, 20>(m) 
    { 
     cerr << "One type" << endl; 
    } 
    }; 
+0

Pensato così. il costruttore non può essere specializzato come funzioni membro, potresti fornire un argomento perché no? –

+0

Risposta in basso: –

6

Assumendo che il davvero significato per A::test ad essere accessibili al pubblico, è potrebbe fare qualcosa di simile:

#include <iostream> 


template <int M> 
struct ABase 
{ 
    ABase(int n) : test_(n > M) 
    {} 

    bool const test_; 
}; 


template <typename T, int M> 
struct A : ABase<M> 
{ 
    A(int n) : ABase<M>(n) 
    {} 
}; 


template <typename T> 
A<T, 20>::A(int n) 
    : ABase<20>(n) 
    { std::cerr << "One type" << std::endl; } 

calci le gomme:

int main(int argc, char* argv[]) 
{ 
    A<int, 20> a(19); 
    std::cout << "a:" << a.test_ << std::endl; 
    A<int, 30> b(31); 
    std::cout << "b:" << b.test_ << std::endl; 
    return 0; 
} 
+1

Buona risposta, impazzire con il sistema di tipi: P –

8

L'unica cosa che non si può fare è usare lo typedef per definire il costruttore. Oltre a questo, si dovrebbe specializzare il A<string,20> costruttore in questo modo:

template<> A<string,20>::A(int){} 

Se si vuole A<string,20> avere un diverso costruttore rispetto alla generica A, è necessario specializzarsi tutta A<string,20> classe:

template<> class A<string,20> { 
public: 
    A(const string& takethistwentytimes) { cerr << "One Type" << std::endl; } 
}; 
0

ne dite:

template<typename T, int M, bool dummy = (M > 20) > 
class A { 
public: 
    A(int m){ 
     // this is true 
    } 

}; 

template<typename T, int M> 
class A<T,M,false> { 
public: 
    A(int m) { 
    //something else 
    } 
}; 
0

La migliore soluzione sono stato in grado di elaborare per questa situazione è quello di utilizzare una "funzione di supporto del costruttore":

template <typename T, int M> class A; 
typedef A<std::string, 20> one_type; 
typedef A<std::string, 30> second_type; 

template <typename T, int M> 
class A { 
private: 
    void cons_helper(int m) {test= (m>M);} 
public: 
    A(int m) { cons_helper(m); } 

    bool test; 
}; 

template <> 
void one_type::cons_helper(int) { cerr << "One type" << endl;} 
0

questo può essere un po 'in ritardo, ma se si ha accesso a c++11 è possibile utilizzare per SFINAE realizzare proprio quello che si vuole:

template <class = typename std::enable_if< 
    std::is_same<A<T,M>, A<std::string, 20>>::value>::type // Can be called only on A<std::string, 20> 
    > 
    A() { 
    // Default constructor 
    } 

Working example

Problemi correlati