Modèle de classes avec des constructeurs
De considérer les éléments suivants exemple artificiel basé sur un modèle de définition de tableau:
template <typename t, unsigned int n> class TBase
{
protected:
t m_Data[n];
//...
};
template <typename t, unsigned int n> class TDerived : public TBase<t, n>
{
TDerived()
{
}
};
Je peut se spécialiser ce type un constructeur par défaut pour un tableau de taille 2 comme suit:
template <typename t> class TDerived<t, 2> : public TBase<t, 2>
{
public:
TDerived(const t& x0, const t& x1)
{
m_Data[0] = x0;
m_Data[1] = x1;
}
};
int main()
{
TDerived<float, 2> Array2D_A(2.0f, 3.0f); //uses specialised constructor
TDerived<float, 3> Array3D_A; //uses default constructor
return 0;
}
Est-il un autre moyen que je peux créer une classe qui dispose de différentes options constructeur heurte paramètres du modèle au moment de la compilation, sans l'exigence d'une classe complète de la spécialisation pour chaque variation?
En d'autres termes, est-il une manière que je peux avoir constructeurs spécialisés dans le TBase
de la classe sans le besoin pour l'étape intermédiaire de la création de TDerived
tout en préservant la fonctionnalité de TBase
?
Quel compilateur et la version utilisez-vous, a-t-elle de C++0x soutien?
Rodríguez - dribeas je switch entre MSVC 2008/2010 donc à la fois oui et non.
Pourquoi ne pas mettre dans tous les constructeurs? Ils ne sont pas être instanciée, sauf si elles sont utilisées.
Rodríguez - dribeas je switch entre MSVC 2008/2010 donc à la fois oui et non.
Pourquoi ne pas mettre dans tous les constructeurs? Ils ne sont pas être instanciée, sauf si elles sont utilisées.
OriginalL'auteur Munro | 2011-08-11
Vous devez vous connecter pour publier un commentaire.
Je pense découlant de votre classe à partir d'une classe de base n'est pas pertinente à la question ici, c'est un simple détail de l'implémentation. Ce qui vous semble vraiment être après si il y a une partie de spécialiser les fonctions de membres, comme le constructeur. Voulez-vous quelque chose de ce genre?
Cela ne fonctionne pas. Vous avez toujours à se spécialiser la classe entière. La raison en est simple: Vous devez connaître le type complet de la classe de première avant vous savez même membre dont les fonctions existent. Considérez les points suivants simples situation:
Maintenant
Bar<T>::somefunction()
dépendT
, mais uniquement la fonction existe quandT
n'est pasint
, parce queBar<int>
est tout à fait différent de la classe.Ou même envisager une autre spécialisation
template <> class Bar<double> : public Zip {};
- même le caractère polymorphe d'une classe peut être totalement différente dans un domaine de spécialité!Donc la seule façon que vous pouvez fournir
spécialisationsnouvelles déclarations de membres, y compris les constructeurs, est par la spécialisation de l'ensemble de la classe. (Vous peut de spécialiser les définition de fonctions existantes, voir @Alf réponse.)Hm, OK, si vous avez des modèles de membre, vous pouvez vous spécialiser ceux individuellement. Mais je voulais dire "se spécialisent membres sur les paramètres de la classe". Comment mieux dire que?
vous pouvez vous spécialiser membres. E. g. voir ma réponse. 🙂
Je vois, mais c'est différent, parce que vous êtes de ne pas changer la signature, de sorte que vous êtes spécialisé définition. Dans mon exemple, on ne pouvait pas se spécialisent
template<> Bar<int>::somefunction(const int&)
, car il n'existe pas. Cela devrait être précisé...OK, j'ai mal compris. Et à la révision de texte, je suis retrait downvote. 🙂 Bien, sauf qu'il a déjà été supprimé, je ne comprends pas. Hein.
OriginalL'auteur Kerrek SB
Il existe essentiellement deux options que je vois à cela:
Utiliser un variadic fonction pour la construction (ie. "..." la notation), vous pouvez utiliser la valeur n à l'intérieur de cette fonction pour obtenir vos arguments sur la pile. Cependant, le compilateur ne vérifie pas au moment de la compilation si l'utilisateur fournit le bon nombre d'arguments.
Utiliser certaines graves modèle de magie pour permettre à un appel chaning de l'initialisation, qui devrait ressembler à ceci:
vector(2.0f)(3.0f)
. Vous pouvez réellement construire quelque chose qui, au moins, assure à l'utilisateur de ne pas fournir trop d'arguments ici. Cependant tha mécanisme est un peu plus impliqué, je peux assembler un exemple si vous le souhaitez.Il va rhoughly: Créer un basé sur un modèle de classe qui acceptera le nombre d'éléments dans le vecteur de paramètre du modèle N. Toutefois, que cette classe seulement tenir un de ces éléments, et de le laisser dériver d'une classe qui détient moins un élément. Se spécialiser pour N=1 élément pour arrêter la chaîne d'héritage. Définir une méthode comme ceci:
Vector<N-1>& operator()(double e) { element=e; return (Vector<N-1>&)*this; }
, à la spécialisation pour N=1, ce retour invalide ou quelque chose d'autre qui n'a pas de définition de l'opérateur().OriginalL'auteur Droggl
Vous pouvez toujours spécialiser un membre, par exemple
Mais vous voulez effectivement des signatures différentes, il n'est donc pas directement un cas de spécialisation d'un membre.
Une solution consiste alors à déclarer un constructeur avec un argument simple, d'un type dépend des paramètres de modèle.
Alors vous pouvez vous spécialiser que, comme vous le souhaitez.
Cheers & hth.,
P. Steinbach @iammilind Alors que c'est une solution possible, idéalement, je voudrais avoir une spécialisation partielle sur le constructeur, par exemple, en spécifiant une longueur mais pas un type
TBase(const t& x0){}
, avec la spécialisation partielle comme suittemplate <typename t> TBase<t, 1>::TBase (const t& x0)
-- mais il semblerait que ce n'est pas possible.pour la fonction, spécialisation partielle n'est pas autorisée par la norme. Ainsi, vous pouvez donner un essai pour les différents types d', je l'ai mentionné dans ma réponse (si il n'y a pas tellement de types).
OriginalL'auteur Cheers and hth. - Alf
Depuis constructeur est une fonction, vous avez besoin pour bien se spécialiser la classe conteneur afin de résoudre votre problème spécifique. Pas moyen de sortir.
Cependant, les fonctions ne peuvent pas être partiellement spécialisées (dans tous les compilateurs). Supposons donc que si vous savez que vous avez besoin
n = 2
quandt = int or double
puis la suite est une solution de rechange.et ainsi de suite.
[Note: Si vous utilisez MSVC, alors je pense qu'il prend en charge partielle de la spécialisation; dans ce cas, vous pouvez essayer:
bien, je ne suis pas assez sûr pour que.]
Désolé, j'ai relu ton post et je pense que j'ai mal interprété. Vous avez raison, je peux spécialiser le constructeur, mais partielle de la spécialisation des constructeurs (ou fonctions membres d'ailleurs) ne sont apparemment pas autorisé. Je n'étais pas au courant de ça!
vous êtes partielle à l'aide de spécialisation pour le plein
class
. Je suis en train de dire que si vous voulez simplement avoir du constructeur pour<t,2>
il vous suffit ensuite de se spécialiser par le constructeur. Vous n'avez pas à se spécialiser complet de la classe. Dans MSVC, je sais qu'ils permettent la formulation de la spécialisation des méthodes; si ce n'est pas possible, alors vous pouvez choisir ce que je suggère dans mon principale réponse où vous savez quet
va êtreint
,double
,... puis de se spécialiser<int,2>
,<double,2>
.OriginalL'auteur iammilind
Vous pourriez donner les définitions les plus courantes dans le non-classe spécialisée et
static_assert
(BOOST_STATIC_ASSERT pour non C++0x) sur la longueur du tableau. Cela pourrait être considéré comme un hack mais c'est une solution simple à votre problème et coffre-fort.Le "mal" serait variadic arguments.
Puis il y a aussi en C++0x et le bon vieux
make_something
truc qui est plus difficile que l'on pourrait penser.Mon
make_something
aurait bien besoin de quelques ajustements et lecommon_type
partie est un peu fragile. Je peux tripoter un coup de pouce.Macro préprocesseur ensemble à faire de la manière la plus facile moins verbeux.OriginalL'auteur pmr