Je voudrais créer un conteneur personnalisé Container
qui stocke les données dans des tableaux individuels. Cependant, pour faciliter les itérations sur le conteneur, je fournis une "vue" sur le conteneur en surchargeant la fonction operator[]
et retourner une seule structure Value
qui contient toutes les variables du conteneur en tant que références au conteneur réel. Voici ce que j'ai obtenu jusqu'à présent :
#include <iostream>
using namespace std;
struct Value {
Value(int& data) : data_(data) { }
int& data() { return data_; }
int& data_;
};
struct Container {
Value makeValue(int i) { return Value(data_[i]); } // EDIT 1
Value&& operator[](int i) {
// return std::forward<Value>(Value(data_[i]));
return std::forward<Value>(makeValue(i)); // EDIT 1
}
int data_[5] = {1, 2, 3, 4, 5};
};
int main(int, char**)
{
// Create and output temporary
Container c;
cout << c[2].data() << endl; // Output: 3 - OK!
// Create, modify and output copy
Value v = c[2];
cout << v.data() << endl; // Output: 3 - OK!
v.data() = 8;
cout << v.data() << endl; // Output: 8 - OK!
// Create and output reference
Value&& vv = c[2];
cout << vv.data() << endl; // Output: 8 - OK, but weird:
// shouldn't this be a dangling reference?
cout << vv.data() << endl; // Output: 468319288 - Bad, but that's expected...
}
Le code ci-dessus fonctionne pour autant que je puisse dire, mais je me demande si j'utilise la meilleure approche ici :
- Est-il correct de renvoyer le
Value
comme une référence rvalue si je veux éviter une copie inutile ? - Est-ce que l'utilisation de
std::forward
correct ? Dois-je utiliserstd::move
(les deux fonctionneront dans cet exemple) ou autre chose ? - Le résultat du programme compilé est indiqué dans les commentaires. Existe-t-il un moyen d'éviter la référence pendante lorsque je déclare
Value&& vv...
(ou même l'interdire syntaxiquement) ?
EDIT 1
J'ai fait un petit changement dans le code source pour que les Value
n'est pas directement créée dans le operator[]
mais dans une autre fonction d'aide. Cela changerait-il quelque chose ? Devrais-je utiliser la makeValue(int i)
comme indiqué ou dois-je utiliser la méthode std::move
/ std::forward
ici ?