2009-12-14 2 views
7

J'ai une classe de modèle A < T, int> et deux typedefs A < chaîne, 20> et A < chaîne, 30>. Comment remplacer le constructeur pour une chaîne A <, 20>? Ce qui suit ne fonctionne pas:spécialisation de modèle C++ du constructeur

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

je voudrais la classe A < std :: string, 20> pour faire quelque chose que l'autre classe ne fonctionne pas. Comment puis-je faire cela sans changer le constructeur A: A (int)?

+0

Qu'est-ce que vous essayez d'obtenir les classes à faire? – GManNickG

+0

La question n'est pas claire. BTW, one_type n'a pas de constructeur vide, il a un constructeur avec un paramètre int. – Drakosha

Répondre

1

Vous ne pouvez pas avec votre approche actuelle. one_type est un alias à une spécialisation de modèle particulière, donc il obtient n'importe quel code que le modèle a.

Si vous voulez ajouter du code spécifique à one_type, vous devez déclarer comme une sous-classe d'une spécialisation, comme ceci:

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

Pensée ainsi. constructeur ne peut pas être spécialisé en tant que fonctions membres, pourriez-vous fournir un argument pour pourquoi pas? –

+0

Répondu ci-dessous: –

6

En supposant que votre vraiment être accessible au public destinés à A::test, vous pourrait faire quelque chose comme ceci:

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

les pneus coup de pied:

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

Bonne réponse, devenir fou avec le système de type: P –

8

La seule chose que vous ne pouvez pas faire est d'utiliser le typedef pour définir le constructeur. En dehors de cela, vous devez spécialiser le constructeur A<string,20> comme ceci:

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

Si vous voulez A<string,20> avoir un différent constructeur que le A générique, vous avez besoin de se spécialiser toute la classe A<string,20>:

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

Que diriez-vous:

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

Le meilleur solution que j'ai été en mesure de trouver cette situation est d'utiliser une « fonction d'aide du constructeur »:

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

Cela peut être un peu en retard, mais si vous avez accès à c++11 vous pouvez utiliser SFINAE à accomplir tout ce que vous voulez:

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

Questions connexes