Considérez le code suivant:
#include <vector> struct A { explicit A(int i_) : i(i_) {} int i; }; int main() { std::vector<int> ints; std::vector<A> As(ints.begin(), ints.end()); }
6 Réponses :
Je pense que cela dépend de la façon dont std :: vecteur comme (itérateur, itérateur) code> est implémenté dans votre implémentation particulière de la STL. P>
Le comportement de la bibliothèque standard n'est pas censé dépendre de la mise en œuvre.
Là encore, il y a des endroits (très rares) où la norme peut être interprétée en deux manières non équivalentes.
Ce code ne compile pas à Comeau:
Foo foo = (Foo)5;
Oui, il devrait compiler. Si le constructeur n'est pas utilisé, son explicite n'est pas un problème. P>
Si le constructeur n'est pas utilisé, comment autrement conversons-nous d'un INT à un A?
Rien n'est créé et rien n'est converti - les deux vecteurs sont vides
Le comportement est le même si quelque chose est inséré dans le vecteur "INTS" avant la construction de "comme".
C'est une question plutôt délicate, et peut-être que VisualStudio ait raison et le comeau faux (cela semble vraiment difficile à croire).
La norme Si Word Lisez par mot, définit ce constructeur de vecteur en termes de em> Copier constructeur em> (voir citation), et cela signifie littéralement que l'objet obtenu par la déséroférance doit d'abord être converti en Le type T, puis le constructeur de copie doit être appelé. À ce stade, avec un constructeur explicite, le code ne doit pas compiler. P>
Il semble raisonnable de s'attendre à une implémentation, d'autre part, d'appeler directement un constructeur prenant comme argument l'itérateur déréférencé, auquel cas la L'appel du constructeur serait explicite et le code devrait donc compiler. Cela irait à l'encontre de la formulation exacte de la citation ci-dessous, car le constructeur copy em> est défini pour un type donné T comme constructeur qui prenant une seule référence éventuellement constante à un objet de type T. P > Je ne peux penser à un argument raisonnable de ne pas utiliser l'approche Comeau, et je pense que c'est juste un avis personnel) est que le libellé de la norme en ce qui concerne la complexité du constructeur de vecteur devrait probablement être retraité comme nécessitant seulement n appels vers le constructeur T approprié em>, le cas échéant, il faudrait être défini comme le constructeur qui correspond à l'appel Complexité: le vecteur de modèle de constructeur (INTTÉTRAITOR
Tout d'abord, l'intrigeur dernier) ne fait que
N Appels vers le constructeur de copie de T
(où n est la distance entre
premier et dernier) et aucune réaffectation
Si les itérateurs d'abord et dernier sont de
transmettre, bidirectionnel ou aléatoire
Catégories d'accès. Ça rend la commande n
appelle au constructeur de copie de T et
Commandez le journal des réaffectations s'ils sont
juste des itérateurs d'entrée. P>
blockQuote> Je voudrais savoir comment le compilateur VS se comporte lorsque vous indiquez: p> avec g ++ Le résultat est que t (* premier) code> (c'est-à-dire une prise de constructeur Un
INTTÉTRATEDATORATOR :: VALUE_TYPE CODE> (par valeur ou éventuellement une référence constante), ou le constructeur de copie T après une conversion implicite de
INTTÉTRATORATOR :: value_type code> à t. p> < p> 23.2.4.1 [lib.vector.cons] / 1 p>
T2 :: opérateur T1 < / code> n'est pas appelé, mais les éléments de
v1 code> sont construits directement à partir des éléments dans
v2 code>. Je suppose que avec vs le compilateur utiliserait
t1 :: opérateur t1 code> pour convertir de chaque élément dans
v2 code> à un élément T1, puis appelez le constructeur de copie. Est-ce vrai? P> p>
En fait, essayant de compiler votre code avec le compilateur VS donne une erreur (C2664): 'std :: allocator <_ty> :: construction': impossible de convertir le paramètre 2 de 'T2' en 'const T1 &' avec [_ty = T1] Raison: impossible de convertir de "T2" en "const t1" Aucun opérateur de conversion défini par l'utilisateur disponible pouvant effectuer cette conversion ou que l'opérateur ne peut pas être appelé.
Je viens de tester avec VS2010 Beta, et cela compile non seulement, mais s'exécute avec le même comportement que g ++: le constructeur t1 (t2 const &) code> est appelé.
Cela revient vraiment à une question de la manière dont la bibliothèque STL est mise en œuvre et non une question de spécification de langue. Il n'y a rien dans la spécification de la langue qui l'interdirait de travailler, pas plus que cela n'exigerait rien que cela fonctionne. P>
Si le constructeur STL :: vecteur a été écrit pour essayer une conversion implicite à l'aide de l'opérateur d'affectation, alors cela échouerait. Il est plus probable que l'implémentation Microsoft STL utilise l'optimisation de la valeur de retour lors de l'initialisation via un appel de constructeur, auquel cas ce code fonctionnerait bien. P>
Il est important de noter que la seule raison de ce travail est que le constructeur de vecteur STL :: vecteur est modélisé et la seule exigence est qu'il s'agit d'un altérateur, ou de plus précisément qu'il prend en charge toutes les fonctionnalités requises d'un itérateur d'entrée. . P>
J'aimerais également souligner que ceci est un excellent exemple de la raison pour laquelle il est souvent difficile d'écrire un code multi-plate-forme. Parfois, vous vous retrouvez avec des problèmes dans lesquels ni le compilateur ne dévient nécessairement de la norme linguistique, mais le code n'est toujours pas portable. P>
J'ai examiné la mise en œuvre de la STL de GCC et cela devrait avoir un comportement similaire. Voici pourquoi. P>
vecteur code> sont initialisés par un modèle de fonction générique qui accepte tous les deux types x code> et v code> et appelle neuf ( p) x (v) code> où v code> est un v code> (je paraphrase un peu). Cela permet une conversion explicite. LI>
- Éléments d'un
SET CODE> ou MAP CODE> sont initialisés par une fonction de membre privé de _tree code> qui attend spécifiquement un T const & code> à transmettre. Cette fonction de membre n'est pas un modèle (au-delà d'être membre d'un modèle), donc si la valeur initiale ne peut pas être convertie implicitement en t code >, l'appel échoue. (Encore une fois, je simplifie le code.) Li>
ul>
La norme ne nécessite pas que le travail de conversion explicite ou cette conversion implicite ne fonctionne pas lors de l'initialisation d'un conteneur avec une plage. Il dit simplement que la plage est copiée dans le conteneur. Définitivement ambiguë pour votre but. P>
Surprenant une telle ambiguïté existe, compte tenu de la manière dont ils ont déjà affiné la norme en tenant compte de problèmes tels que celui que j'avais il y a quelques semaines. P>
Réponse indirectement ici: Stackoverflow.com/Questtions/1943228/...
Je viens d'écrire une réponse ici en fonction de cette question + réponse, mais cela ne s'applique pas vraiment, car
std :: vecteur :: itérateur code> n'est pas un type intégral, et le remplissage constructeur n'est pas appelé. Donc je l'ai supprimé. Je pense que tout ce que je peux dire, c'est que la norme ne interdit i> Conversion explicite dans tout constructeur de conteneurs.
Vs 2010 Beta se comporte comme Comeau et GCC.