2010-12-02 33 views
1

J'ai beaucoup d'exemples du code ci-dessous:Comment puis-je remplir un vecteur avec des itérateurs d'un type différent?

struct foo1 
{ 
    foo1(int ii = 0, int jj = 0) 
    { 
     this->ii = ii; 
     this->jj = jj; 
    } 

    int ii; 
    int jj; 
}; 

struct foo2 
{ 
    foo2() 
    { 
    } 

    foo2(const foo1& f) 
    { 
     this->f = f; 
    } 

    foo1 f; 
}; 
typedef std::vector<foo2> foo_v; 

typedef std::set<int> bar_s; 

bar_s barSet; 
barSet.insert(1); barSet.insert(2); barSet.insert(3); 
barSet.insert(4); barSet.insert(5); barSet.insert(6); 

... 

foo_v fooVec; 
for (bar_s::iterator b = barSet.begin(); b != barSet.end(); ++b) 
    fooVec.push_back(foo2(*b)); 

Comment puis-je améliorer le code où il est le remplissage d'un nouveau vecteur de foo2?

Je pensais quelque chose le long des lignes de:

std::remove_copy_if(barSet.begin(), barSet.end(), 
        std::back_inserter(fooVec), ...) 

mais je me bats pour trouver un moyen de lier le type int à de nouvelles instances de la struct foo2.


Note:

std::copy(barSet.begin(), barSet.end(), std::back_inserter(fooVec)); 

me donne l'erreur suivante:

Erreur 1 erreur C2679: binaire '=': aucun opérateur trouvé qui prend un opérande à droite de type ' int '(ou il n'y a pas de conversion acceptable)

+0

Si vous déréférencer un itérateur sur 'bar_s', cela entraînerait un' int'. Maintenant, 'int' peut déjà être converti en' foo', vous devriez donc être capable d'insérer la valeur derrière un itérateur sur 'bar_s' dans' foo_v' – Mephane

Répondre

3
std::copy(barSet.begin(), barSet.end(), std::back_inserter(fooVec)); 

est convera ble à `foo '(le seul constructeur peut être appelé avec un argument int et il n'est pas explicite).

Error 1 error C2679: binary '=' : no operator found which takes a right-hand operand of type 'int' (or there is no acceptable conversion)

C'est parce que foo2 ne peut pas être contstructed à partir int, seulement à partir foo1 et une seule étape de conversion implicite est autorisée. Vous pouvez vous std :: transform:

std::transform(barSet.begin(), barSet.end(), 
       std::back_inserter(fooVec), 
       boost::lambda::constructor<foo2>()); 

Le boost :: lambda :: constructeur() peut être remplacé par std :: fun_ptr (makeFoo2):

foo2 makeFoo2(const foo& f) { return f; } 
+0

Désolé, j'ai modifié mon code ci-dessus - j'ai dans mon réel code plusieurs constructeurs. – Alan

+0

Pas de problème. foo a toujours un constructeur qui peut être appelé avec un argument int. Vous pouvez ajouter encore un autre constructeur, par ex. à partir de double ou de la chaîne ou quoi que vous quoi, et vous êtes toujours en mesure de construire implicitement foo de int (et en outre de double, chaîne, etc). – Begemoth

+0

Les conteneurs STL ont également un constructeur à partir de deux itérateurs, ce qui va copier la plage spécifiée d'un autre conteneur. – Begemoth

0

Vous pouvez utiliser le constructeur du vecteur cela prend une paire d'itérateurs.

foo_v fooVec(barSet.begin(), barSet.end()); 

Compte tenu des constructeurs de foo, int est implicitement convertible en foo.

+0

Toutes mes excuses, mais mon exemple était faux - j'ai modifié mon code. – Alan