Remplir une collection en faisant une "conversion"
Le problème exposé dans ce sujet a été résolu.
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 !
Est-ce vraiment nécessaire d'avoir une fonction qui donne accès à l'ensemble de la collection ? Ou une paire d'itérateurs (constants) suffirait-elle pour y accéder ?
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 ?
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()).
Merci pour les deux tuyaux (et vive boost !), j'ai l'impression que indirect_iterator fait parfaitement le job.
Connectez-vous pour pouvoir poster un message.
Connexion
Pas encore membre ?
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