O seguinte não compila:
#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;
}
O erro do compilador é: error: assignment of read-only reference 's'
Agora, no meu caso atual, a lista é feita de variáveis de membro em uma classe.
Agora, isso não funciona porque a expressão se torna um initializer_list<int>
que realmente copia a, b, ce ed - portanto, também não permite modificações.
Minha pergunta é dupla:
Existe alguma motivação por trás de não permitir escrever um loop for baseado em intervalo dessa maneira? por exemplo. talvez possa haver um caso especial para expressões de chaves nuas.
Qual é uma maneira pura e sintática de corrigir esse tipo de loop?
Algo nessa linha seria preferido:
for (auto& s : something(a, b, c, d)) {
s = 1;
}
Não considero a indireção do ponteiro uma boa solução (ou seja {&a, &b, &c, &d}
) - qualquer solução deve fornecer referência ao elemento diretamente quando o iterador é desassistido .
fonte
{ &a, &b, &c, &d }
.initializer_list
é principalmente uma visão daconst
matriz.{ &a, &b, &c, &d }
, também não vai querer:for (auto& s : std::initializer_list<std::reference_wrapper<int>>{a, b, c, d}) { s.get() = 1; }
Respostas:
Os intervalos não são tão mágicos quanto as pessoas gostariam. No final, deve haver um objeto no qual o compilador possa gerar chamadas para uma função membro ou para uma função livre
begin()
eend()
.O mais próximo que você provavelmente poderá chegar é:
fonte
std::vector<int*>
.auto s
ouauto* s
nãoauto& s
.Apenas outra solução dentro de uma ideia de wrapper:
Então:
saídas
fonte
De acordo com o padrão §11.6.4 Inicialização de lista / p5 [dcl.init.list] [ Mina de Ênfase ]:
Assim, seu compilador está reclamando legitimamente (isto é,
auto &s
deduzint const& s
e você não pode atribuir as
no loop for variado).Você pode aliviar esse problema introduzindo um contêiner em vez de uma lista de inicializadores (por exemplo, `std :: vector ') com' std :: reference_wrapper ':
Demonstração ao vivo
fonte
for (auto& s : {a, b, c, d})
não funciona. Quanto ao motivo pelo qual a norma possui essa cláusula ..... você teria que perguntar aos membros do comitê de padronização. Como muitas dessas coisas, o raciocínio pode ser qualquer coisa entre "Não consideramos o seu caso em particular útil o suficiente para nos preocuparmos" até "Muitas outras partes do padrão precisariam ser alteradas para apoiar o seu caso e adiamos a consideração de tudo isso até desenvolvermos um padrão futuro ".std::array<std::reference_wrapper>>
?Para satisfazer essa sintaxe
você pode criar wrapper:
Demo
fonte
std::reference_wrapper
?std::reference_wrapper
exigirias.get() = 1;
.Solução: use um wrapper de referência
Então usado como:
Isso não tenta responder à primeira pergunta.
fonte
Você pode criar uma classe de wrapper para armazenar referência e qual terá o operador de atribuição para atualizar este valor:
Demonstração ao vivo
fonte