Écrit variadic template constructeur
J'ai demandé récemment à cette question, mais maintenant, je tiens à le développer. J'ai écrit la classe suivante:
template <class T>
class X{
public:
vector<T> v;
template <class T>
X(T n) {
v.push_back(n);
}
template <class T, class... T2>
X(T n, T2... rest) {
v.push_back(n);
X(rest...);
}
};
Lors de la création d'un objet à l'aide
X<int> obj(1, 2, 3); //obj.v containts only 1
Vecteur ne contient que la première valeur, mais pas d'autres. J'ai vérifié et vu que le constructeur est appelé 3 fois, donc je suis probablement la création d'une temp objets et de remplissage de leurs vecteurs, avec le reste des arguments. Comment puis-je résoudre ce problème?
Pourquoi ne pas simplement
Génial! Merci.
Votre classe ne devrait vraiment se
Je suis nouveau en C++11, donc encore de l'apprentissage.
template <typename ...Args> X(Args ...args) : v({args...}) {}
?Génial! Merci.
Votre classe ne devrait vraiment se
std::initializer_list<T>
argument au lieu d'avoir un variadic template constructeur. C'est idiomatiques.Je suis nouveau en C++11, donc encore de l'apprentissage.
OriginalL'auteur Tracer | 2015-03-04
Vous devez vous connecter pour publier un commentaire.
Tout d'abord, votre code ne compile pas pour moi.
J'ai changé de l'extérieur à
U
.Vous avez raison que cela provoque le problème que vous avez donné à la question de détails...
C'est parce que la déclaration
X(rest...)
à la fin de votre constructeur n'est pas récursivement appeler le constructeur de poursuivre l'initialisation de l'objet même; il crée un nouveauX
objet qu'on jette ensuite. Une fois qu'un constructeur corps commence à s'exécuter, il n'est plus possible d'invoquer un autre constructeur, sur le même objet. La délégation doit se produire dans le ctor-initialiseur. Ainsi, par exemple, vous pourriez faire ceci:Qui suce bien que, en raison de l'insertion, au début d'un vecteur n'est pas efficace.
Mieux de prendre un
std::initializer_list<T>
argument. C'est ce questd::vector
lui-même n'.OriginalL'auteur
Tout à fait d'accord avec Brian réponse, mais même si la bonne approche est d'une autre (c'est à dire utiliser initializer_list) s'il vous plaît être conscient (pour le plaisir de le faire correctement dans d'autres circonstances) que variadic template récursivité dans ce cas pourrait être beaucoup plus simple de juste en notant qu'un vide pack est un modèle valide paramètre pack, de sorte que les variadic template constructeur sera appelé une dernière fois avec le bloc-batterie vide, ce qui conduira à essayer de faire appel à un défaut ctor, qui peut être affichée par défaut et de mettre fin à la récursivité.
OIE, ce qui suit de travail et serait beaucoup plus propre de l'OMI:
Encore une fois, je ne dis pas que les modèles et la récursivité sont la bonne chose ici, je signale simplement que seraient-ils nécessaires, il y aurait un moyen plus simple de les utiliser.
OriginalL'auteur
Il n'est pas nécessaire pour la récursivité, en premier lieu -
vous pouvez utiliser le "tableau temporaire" d'un langage et d'écriture
La bonne (et plus complexe) version de cette approche ressemble à ceci:
Version Live
Noter que la prochaine version de C++ seront sans doute les Plier Les Expressions
(v.push_back(e), ...);
OriginalL'auteur
OriginalL'auteur