2009-12-14 21 views
7

Tengo una clase de plantilla A < T, int> y dos typedefs A < cadena, 20> y A < cadena, 30>. ¿Cómo anulo el constructor para una cadena A <, 20>? El siguiente no funciona:C++ plantilla especialización del constructor

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;} 

Me gustaría que la clase A < std :: string, 20> para hacer algo que la otra clase no lo hace. ¿Cómo puedo hacer esto sin cambiar el constructor A: A (int)?

+0

¿Qué está tratando de obtener las clases que se pueden hacer? – GManNickG

+0

La pregunta no está clara. Por cierto, one_type no tiene constructor vacío, tiene constructor con parámetro int. – Drakosha

Respuesta

1

No puede con su enfoque actual. one_type es un alias de una especialización de plantilla en particular, por lo que obtiene cualquier código que tenga la plantilla.

Si desea agregar código específico para one_type, usted tiene que declarar como una subclase de una especialización, como esto:

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

Eso pensé. constructor no se puede especializar como funciones miembro, ¿podría proporcionar un argumento de por qué no? –

+0

Respondido a continuación: –

6

Asumiendo que su realmente significaba para A::test a ser accesibles al público, se podría hacer algo como esto:

#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; } 

patear los neumáticos:

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

Buena respuesta, volviendo loco con el sistema de tipo: P –

8

Lo único que no puede hacer es usar el typedef para definir el constructor. Aparte de eso, usted debe especializar el constructor A<string,20> así:

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

Si quieres A<string,20> tener un constructor diferente que el genérico A, es necesario especializarse toda la clase A<string,20>:

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

¿Qué tal:

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 mejor solución que hemos sido capaces de llegar a esta situación es usar un "constructor de función auxiliar":

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

Esto puede ser un poco tarde, pero si usted tiene acceso a c++11 se puede utilizar para SFINAE lograr precisamente lo que quiere:

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

Cuestiones relacionadas