Questa è una domanda piuttosto complicata, e potrebbe essere il caso che VisualStudio abbia ragione e Comeau torto (questo sembra davvero difficile da credere).
Lo standard se parola letta per parola, definisce tale costruttore vettore in termini di costruttore di copia (vedi citazione), e ciò significa letteralmente che l'oggetto ottenuto dereferenziando all'iteratore deve essere prima convertito nel tipo T e quindi si dovrebbe chiamare il costruttore di copia. A questo punto, con un costruttore esplicito il codice non dovrebbe essere compilato.
Sembra ragionevole prevedere un'implementazione, al contrario, chiamare direttamente un costruttore che prenda come argomento l'iteratore dereferenziato, nel qual caso la chiamata del costruttore sarebbe esplicita e quindi il codice dovrebbe essere compilato.Ciò andrebbe contro l'esatta formulazione nella citazione di seguito, come il costruttore copia è definita per un dato tipo T come un costruttore che prendendo un unico riferimento eventualmente costante ad un oggetto di tipo T.
Non posso pensare ogni ragionevole argomento per non usare l'approccio di Comeau, e credo (questa è solo un'opinione personale) è che la formulazione nello standard rispetto alla complessità del costruttore di vettore dovrebbe probabilmente essere riformulata come richiesto solo N chiamate all'appropriato T costruttore, se del caso dovrebbe essere definito come il costruttore che corrisponde alla chiamata T(*first)
(ovvero, un costruttore che prende un InputIterator::value_type
(in base al valore o eventualmente un riferimento costante) o il const di copia T ructor dopo una conversione implicita da InputIterator::value_type
a T.
23.2.4.1 [lib.vector.cons]/1
Complessità: Il modello costruttore vettoriale (InputIterator primo, InputIterator ultimo) rende solo N chiama il costruttore di copia di T (dove N è la distanza tra prima e l'ultima) e nessuna riallocazione se gli iteratori primo e ultimo sono di di accesso, bidirezionale o casuale categorie di accesso. Effettua le chiamate N al costruttore di copie di T e riassegnazioni del registro degli ordini se sono solo input iteratori.
vorrei sapere come si comporta quando dato il compilatore VS:
struct T1;
struct T2 {
operator T1();
};
struct T1 {
T1(T2 const &) { std::cout << "T1(T2)" << std::endl; }
};
T2::operator T1() {
std::cout << "T2::operator T1" << std::endl;
return T1(*this);
}
int main() {
std::vector<T2> v2;
v2.push_back(T2());
std::vector<T1> v1(v2.begin(), v2.end());
}
Con g ++ il risultato è che T2::operator T1
non si chiama, ma gli elementi in v1
sono costruiti direttamente dagli elementi in v2
. Suppongo che con VS il compilatore utilizzi T2::operator T1
per convertire da ogni elemento in v2
a un elemento T1 e quindi chiamare il costruttore di copie. È così?
Risposta indiretta qui: http://stackoverflow.com/questions/1943228/implicit-constructor-conversion-works-on-explicit-vectorvector-only-sometimes –
Ho appena scritto una risposta in base a tale domanda + risposta, ma in realtà non si applica, dal momento che 'std :: vector :: iterator' non è un tipo integrale e il compilatore di riempimento non viene chiamato. Quindi l'ho cancellato. Penso che tutto quello che posso dire è che lo standard non * proibisce * la conversione esplicita in qualsiasi costruttore di container. –
Potatoswatter
VS 2010 Beta si comporta come Comeau e gcc. –