Comment puis-je forcer un paramètre de modèle T
être une sous-classe d'une classe spécifique Baseclass
? Quelque chose comme ça :
template <class T : Baseclass> void function(){
T *object = new T();
}
Comment puis-je forcer un paramètre de modèle T
être une sous-classe d'une classe spécifique Baseclass
? Quelque chose comme ça :
template <class T : Baseclass> void function(){
T *object = new T();
}
Avec un compilateur compatible avec C++11, vous pouvez faire quelque chose comme ceci :
template<class Derived> class MyClass {
MyClass() {
// Compile-time sanity check
static_assert(std::is_base_of<BaseClass, Derived>::value, "Derived not derived from BaseClass");
// Do other construction related stuff...
...
}
}
J'ai testé ceci en utilisant le compilateur gcc 4.8.1 dans un environnement CYGWIN - cela devrait donc fonctionner dans les environnements *nix également.
Pour moi, ça marche aussi comme ça : template<class TEntity> class BaseBiz { static_assert(std::is_base_of<BaseEntity, TEntity>::value, "TEntity not derived from BaseEntity");
...
Ah oui, c'est une bonne idée. Merci ! Je suppose qu'il n'y a donc aucun moyen de le définir dans la définition du modèle ?
@phant0m : Correct. Vous ne pouvez pas contraindre explicitement les paramètres des modèles (sauf en utilisant des concepts, ce qui a été envisagé pour c++0x mais ensuite abandonné). Toutes les contraintes se produisent implicitement par les opérations que vous effectuez sur lui (ou en d'autres termes, la seule contrainte est "Le type doit supporter toutes les opérations qui sont effectuées sur lui").
Cela exécute le constructeur T(), et nécessite l'existence du constructeur T(). Voir ma réponse pour une façon d'éviter ces exigences.
Pour exécuter moins de code inutile au moment de l'exécution, vous pouvez consulter : http://www.stroustrup.com/bs_faq2.html#constraints qui fournit des classes permettant d'effectuer le test de compilation de manière efficace et de produire des messages d'erreur plus agréables.
En particulier :
template<class T, class B> struct Derived_from {
static void constraints(T* p) { B* pb = p; }
Derived_from() { void(*p)(T*) = constraints; }
};
template<class T> void function() {
Derived_from<T,Baseclass>();
}
Pour moi, c'est la meilleure et la plus intéressante des réponses. N'oubliez pas de consulter la FAQ de Stroustrup pour en savoir plus sur toutes sortes de contraintes que vous pourriez appliquer de la même manière.
En effet, c'est une sacrée réponse ! Merci. Le site mentionné est déplacé ici : stroustrup.com/bs_faq2.html#contraintes
C'est une excellente réponse. Existe-t-il de bons moyens d'éviter les avertissements unused variable 'p'
y unused variable 'pb'
?
Vous n'avez pas besoin de concepts, mais vous pouvez utiliser SFINAE :
template <typename T>
boost::enable_if< boost::is_base_of<Base,T>::value >::type function() {
// This function will only be considered by the compiler if
// T actualy derived from Base
}
Notez que cette méthode n'instancie la fonction que lorsque la condition est remplie, mais qu'elle ne fournit pas d'erreur sensée si la condition n'est pas remplie.
El enable_if
prend un second paramètre de type qui prend la valeur par défaut de void
. T enable_if< true, int >::type
représente le type int
. Je ne comprends pas vraiment votre première question. Vous pouvez utiliser SFINAE pour ce que vous voulez, mais je ne comprends pas bien ce que vous avez l'intention de faire avec cette fonction globale.
Vous pourriez utiliser Contrôle du concept Boost 's BOOST_CONCEPT_REQUIRES
:
#include <boost/concept_check.hpp>
#include <boost/concept/requires.hpp>
template <class T>
BOOST_CONCEPT_REQUIRES(
((boost::Convertible<T, BaseClass>)),
(void)) function()
{
//...
}
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
3 votes
Qu'essayez-vous d'accomplir en faisant cela ?
6 votes
Au contraire, c'est très pertinent. Elle détermine si c'est une bonne idée ou non de mettre du travail dans ce test. Dans de nombreux cas (tous ?), il n'est absolument pas nécessaire d'appliquer ces contraintes vous-même, mais plutôt de laisser le compilateur le faire lors de l'instanciation. Par exemple, pour la réponse acceptée, il serait bon de mettre une vérification pour savoir si
T
dérivé deBaseclass
. Pour l'instant, cette vérification est implicite, et n'est pas visible pour la résolution des surcharges. Mais si une telle contrainte implicite n'est faite nulle part, il semble n'y avoir aucune raison pour une restriction artificielle.1 votes
Oui, je suis d'accord. Cependant, je voulais juste savoir s'il y avait un moyen d'y parvenir ou non :) Mais bien sûr, vous avez un point de vue très valable et je vous remercie de votre perspicacité.
3 votes
Je veux juste m'assurer que T est bien une instance d'une sous-classe ou de la classe elle-même. Le code à l'intérieur de la fonction que j'ai fournie n'est pas du tout pertinent.