Ce qui suit ne se compile pas :
#include <iostream>
int main()
{
int a{},b{},c{},d{};
for (auto& s : {a, b, c, d}) {
s = 1;
}
std::cout << a << std::endl;
return 0;
}
L'erreur du compilateur est: error: assignment of read-only reference 's'
Maintenant, dans mon cas réel, la liste est composée de variables membres sur une classe.
Maintenant, cela ne fonctionne pas parce que l'expression devient un initializer_list<int>
qui copie en fait a, b, c et d - donc ne permet pas non plus la modification.
Ma question est double:
Y a-t-il une motivation derrière ne pas permettre d'écrire une boucle for basée sur une plage de cette façon? par exemple. il pourrait peut-être y avoir un cas particulier pour les expressions d'accolade nue.
Quelle est une manière syntaxique soignée de réparer ce type de boucle?
Quelque chose dans ce sens serait préférable:
for (auto& s : something(a, b, c, d)) {
s = 1;
}
Je ne considère pas l'indirection de pointeur comme une bonne solution (c'est-à-dire {&a, &b, &c, &d}
) - toute solution devrait donner la référence de l'élément directement lorsque l'itérateur est dé-référencé .
la source
{ &a, &b, &c, &d }
.initializer_list
est principalement une vue sur leconst
tableau.{ &a, &b, &c, &d }
, vous ne voudrez pas non plus:for (auto& s : std::initializer_list<std::reference_wrapper<int>>{a, b, c, d}) { s.get() = 1; }
Réponses:
Les gammes ne sont pas aussi magiques que les gens le souhaiteraient. En fin de compte, il doit y avoir un objet sur lequel le compilateur peut générer des appels à une fonction membre ou à une fonction libre
begin()
etend()
.Le plus proche que vous pourrez probablement venir est:
la source
std::vector<int*>
.auto s
ouauto* s
nonauto& s
.Juste une autre solution dans une idée d'emballage:
Alors:
les sorties
la source
Selon la norme §11.6.4 Initialisation de liste / p5 [dcl.init.list] [ Emphasis Mine ]:
Ainsi, votre compilateur se plaint légitimement (c'est-à-dire,
auto &s
déduitint const& s
et vous ne pouvez pas attribuer às
dans la boucle à distance).Vous pouvez atténuer ce problème en introduisant un conteneur au lieu d'une liste d'initialisation (par exemple, `std :: vector ') avec' std :: reference_wrapper ':
Démo en direct
la source
for (auto& s : {a, b, c, d})
ne fonctionne pas. Quant à savoir pourquoi la norme contient cet article ... vous devriez demander aux membres du comité de normalisation. Comme beaucoup de ces choses, le raisonnement pourrait être n'importe quoi entre "Nous n'avons pas considéré que votre cas particulier était suffisamment utile pour se soucier de" jusqu'à "Trop d'autres parties de la norme devraient changer pour soutenir votre cas, et nous avons reporté l'examen de tout cela jusqu'à ce que nous développions une future norme ".std::array<std::reference_wrapper>>
?Pour satisfaire cette syntaxe
vous pouvez créer un wrapper:
Démo
la source
std::reference_wrapper
t-il?std::reference_wrapper
nécessiteraits.get() = 1;
.Solution: utilisez un wrapper de référence
Puis utilisé comme:
Cependant, cela n'essaie pas de répondre à la première question.
la source
Vous pouvez créer une classe wrapper pour stocker la référence et qui aura l'opérateur d'affectation pour mettre à jour cette valeur:
Démo en direct
la source