Remplir une collection en faisant une "conversion"

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Salut,

J'ai une classe qui ressemble à peu près à ça :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class A
{
public:
    A(std::vector<std::unique_ptr<Contained>>&& containeds)
    : m_containeds{std::move(containeds)}
    {
    }

    std::vector<std::reference_wrapper<const Contained>> getContaineds();

private:
    std::vector<std::unique_ptr<Contained>> m_containeds;
};

Comme vous voyez, la classe contient un vector de unique_ptr mais le getter renvoie un vector de reference_wrapper. J'ai donc essayé de l'écrire de la meilleure manière possible, et j'obtiens cela :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
std::vector<std::reference_wrapper<const Contained>> getContaineds()
{
    std::vector<std::reference_wrapper<const Contained>> refs{m_containeds.size()};

    using std::begin;
    using std::end;

    auto it = begin(m_containeds);

    std::generate(begin(refs), end(refs), [&it](){return std::cref(**it++);});

    return refs;
}

Que pensez-vous de cette solution ? Est-il possible de faire mieux ?

Merci d'avance ! :)

Édité par mehdidou99

Plus on apprend, et, euh… Plus on apprend. | Coliru, parfait pour tester ses codes sources !

+0 -0
Auteur du sujet

Salut, il est vrai que renvoyer un range est plus judicieux. Cependant, j'ai d'autres données du même genre qui ne sont pas dans des collections (i.e des attributs de la forme std::unique_ptr<...> m_attr), et les getters correspondants (je rassure : exposer les données en lecture est bien un service que l'on est en droit d'attendre de la classe) renvoient directement des références, et je souhaite donc uniformiser. Le mieux serait donc d'écrire une classe implémentant un RandomAccessIterator avec un opérateur de déréférencement qui déréférence deux fois. Qu'en pensez-vous ?

Plus on apprend, et, euh… Plus on apprend. | Coliru, parfait pour tester ses codes sources !

+0 -0

Cette réponse a aidé l'auteur du sujet

C'est en effet plus judicieux de faire un itérateur avec double déréférencement. Boost propose un iterator_adaptor pour n'avoir qu'à surcharger dereference(). C'est probablement aussi possible de le faire avec deux indirect_iterator. Il y a également la solution d'écrire soit même l'itérateur, même si c'est plus barbant qu'autre chose.

Le tout wrapper dans un range pour plus de commodité (begin(), end(), operator[], size(), empty()).

+1 -0
Auteur du sujet

Merci pour les deux tuyaux (et vive boost !), j'ai l'impression que indirect_iterator fait parfaitement le job.

Édité par mehdidou99

Plus on apprend, et, euh… Plus on apprend. | Coliru, parfait pour tester ses codes sources !

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte