2008-11-24 9 views
3

Tenir compte de l'utilisation suivante des paramètres du modèle de modèle ...Comment déclarer/définir une classe avec des paramètres de modèle de modèle sans l'aide d'un paramètre de modèle supplémentaire

#include <iostream> 

template <typename X> 
class A 
{ 
    X _t; 
public: 
    A(X t) 
     :_t(t) 
    { 
    } 
    X GetValue() 
    { 
     return _t; 
    } 
}; 

template <typename T, template <typename T> class C > 
class B 
{ 
    C<T> _c; 
public: 
    B(T t) 
     :_c(t) 
    { 
    } 
    T GetValue() 
    { 
     return _c.GetValue(); 
    } 
}; 

using namespace std; 

int main() 
{ 
    B<int, A> b(10); 
    cout<<b.GetValue(); 
    return 0; 
} 

est-il un moyen par lequel le T des paramètres du modèle peut être enlevé? Par exemple, y a-t-il un moyen de faire le travail suivant?

//Does not compile 
template <template <typename T> class C > 
class B 
{ 
    C _c; 
public: 
    B(T t) 
     :_c(t) 
    { 
    } 
    T GetValue() 
    { 
     return _c.GetValue(); 
    } 
}; 

int main() 
{ 
    B< A<int> > b(10); 
    cout<<b.GetValue(); 
    return 0; 
} 

Répondre

8

Je suppose que vous êtes après X, ainsi que A, dans votre code.

Le schéma habituel est d'avoir

template<typename C> 
struct B 
{ 
    C c; 
}; 

puis, les classes à l'intérieur admissibles pour la substitution:

template<typename X> 
class A 
{ 
    typedef X type_name; 
    X t; 
}; 

Ensuite, vous pouvez accéder au paramètre de modèle à l'aide C::type_name.

+0

Merci pour la réponse, mais j'ai finalement découvert cela moi-même. J'étais en train d'éditer la question et de poster mon travail mais apparemment j'étais venu au bon endroit pour poser cette question! –

+0

notez que la réponse de Sunlight est meilleure que la mienne, puisqu'il a compris ce que vous voulez. Pas besoin de se rétablir comme je vous l'ai montré.Cela ne serait nécessaire que si vous utilisez A , mais que vous avez parfois besoin d'un A . Ou si la vue de l'utilisateur est A , mais que vous utilisez A . –

+0

+1! Je cherchais un moyen de recevoir une référence à n'importe quel conteneur standard, et utiliser ainsi le type 'C :: value_type' était vraiment utile. Merci! – Vargas

1

Quel est le problème:

template <typename C > 
struct B 
{ 
    C c; 
}; 

int main() 
{ 
    B< A<int> > b; 
    return 0; 
} 
+0

Mon mauvais, le problème n'a pas été entièrement spécifié. C'est maintenant. –

4

Ce n'est pas possible. Notez qu'il s'agit d'un malentendu courant: A<int> n'est plus un modèle de classe! Donc, il ne conviendrait pas à un paramètre modèle-modèle, mais devrait être acceptée en utilisant un type paramètre:

template<typename C> 
struct B { 
    C c; 
}; 

B< A<int> > b; 

Votre façon d'utiliser un paramètre séparé est bien.

Si vous voulez accepter A<int> mais que vous souhaitez re-lier à un autre paramètre, vous pouvez utiliser ce modèle, également utilisé par la norme-allocateurs:

template<typename T> 
struct A { 
    template<typename U> 
    struct rebind { 
     typedef A<U> type; 
    }; 
}; 

template<typename C> 
struct B { 
    typename C::template rebind<float>::type c; 
}; 

B< A<int> > b; 

Maintenant, B< A<int> >::c est de type A<float>. Le typename avant C:: indique au compilateur que le ::type à la fin est un type et non un membre statique non-type. Le template après C:: indique au compilateur que le rebind<float> est un instanciation de modèle, et non une comparaison.

+0

Ok, cool! Bonne réponse mais malheureusement il ne peut y avoir qu'une seule réponse et je pense que @sunlight a posté sa solution plus tôt. J'ai upvoted votre réponse. –

1

Vous pouvez imbriquer des paramètres. C'est-à-dire que la valeur d'un paramètre peut elle-même être paramétrée.

template <typename X> 
struct A 
{ 
    X t; 
}; 

template <typename C> 
struct B 
{ 
    C c; 
}; 

int main() 
{ 
    B< A<int> > b; 
    return 0; 
} 

Dans cet exemple, la déclaration de b dans main() crée une spécialisation de A en utilisant int comme paramètre, il crée une spécialisation de B en utilisant A<int> comme paramètre. Ainsi, dans la spécialisation de B, C est A<int>.

+0

Votre solution est correcte selon la question originale mais j'ai ajouté quelques détails que j'ai raté la première fois. Merci. –