Je me demande est une façon de définir des restrictions sur la classe de modèles? similaire => in haskell p>
Spécifiez que chaque type substitué dans le modèle doit avoir un ancêtre spécifique (réaliser une certaine interface).
5 Réponses :
Vous pouvez Utilisez boost_static_assert code> ou une bibliothèque similaire pour affirmer vos restrictions sur le paramètre de modèle.
Par exemple: P>
template < class B >
class A {
BOOST_STATIC_ASSERT(boost::is_base_of<C, B>);
public:
B * obj;
int f() {
return B::x + this->obj->f();
}
};
Vous pouvez utiliser un truc comme celui-ci (si vous ne voulez pas utiliser Boost):
test.cpp
test.cpp(18) : error C2039: 'TEMPLATE_REQUIRES_BASE_CLASS' : is not a member of 'Incorrect'
test.cpp(12) : see declaration of 'Incorrect'
test.cpp(25) : see reference to class template instantiation 'TMPL<T>' being compiled
with
[
T=Incorrect
]
test.cpp(18) : error C2065: 'TEMPLATE_REQUIRES_BASE_CLASS' : undeclared identifier
test.cpp(18) : error C2057: expected constant expression
Ce code n'a pas échoué sous G ++ 4.4, en raison d'une raison inconnue. En général, je dirais que dans ce cas, une énumération est généralement utilisée: Enum {template_requires_base_class = 0}; Cela présente l'avantage supplémentaire de l'échec comme prévu sous G ++.
@Semen, GCC n'est pas conforme. La norme nécessite une instanciation de la déclaration du membre de données lorsque la classe est implicitement instanciée et qu'un initialiseur en classe fait partie de la déclaration au lieu de la définition de celui-ci. Toutefois, la norme est légèrement claire, disant "l'initialisation (et tous les effets secondaires associés) d'un élément de données statique ne se produit que si l'élément de données statique est utilisé lui-même d'une manière qui exige la définition du membre de données statique. " - Cette règle semble toutefois s'appliquer uniquement à un initialisateur hors classe (n'a aucun sens autrement)
@Johannes: Merci pour l'explication, je pensais que je devais devenir folle quand elle construisait bien ... mais je suppose que Enum est toujours plus simple à utiliser. (Je suis juste après Vandervourde :)
Une future version de C ++ prend en charge cette utilisation de manière native avec des concepts (qui ne l'ont pas transformé en C ++ 11).
Un moyen d'aborder le problème consiste à utiliser la spécialisation sur un paramètre de modèle factice: P >
class C {};
template <class B, class dummy=void>
class A;
template <class B>
class A<B, typename enable_if<is_base_and_derived<C, B> >::type>
{
// class definition here
};
struct D : C {};
A<D> d; // fine
A<int> n; // compile error - undefined class A<B>
Les modèles sont en quelque sorte de taper du canard en C ++.
Si votre classe prend en charge tout ce que le modèle utilise, il peut être utilisé comme argument de modèle, sinon il ne peut pas. P>
Si dans votre modèle vous avoir quelque chose comme p> alors vous exécutez que T est dérivé de C (ou au moins compatible avec les pointeurs) p> p>
Les travaux suivants dans VC10 à l'aide de static_assert. Je viens de voir cela et je n'ai pas vraiment creusé beaucoup dans ce que static_asserat fait réellement - peut-être que quelqu'un d'autre peut répondre à cela. La sortie du compilateur étant: p> 1>d:\temp\aaa\aaa\aaa.cpp(25): error C2338: T not derived from Base
1> d:\temp\aaa\aaa\aaa.cpp(41) : see reference to class template instantiation 'A<T>' being compiled
1> with
1> [
1> T=SomeRandomClass
1> ]
Pourquoi pensez-vous avoir besoin de cela?
Dupliqué possible de Modèle de classe C ++ de base spécifique
sooooo pas une question débutante :-). Les concepts sont en réalité assez controversés.