Vamos imaginar que temos uma estrutura para manter 3 duplos com algumas funções-membro:
struct Vector {
double x, y, z;
// ...
Vector &negate() {
x = -x; y = -y; z = -z;
return *this;
}
Vector &normalize() {
double s = 1./sqrt(x*x+y*y+z*z);
x *= s; y *= s; z *= s;
return *this;
}
// ...
};
Isso é um pouco artificial para simplificar, mas tenho certeza de que você concorda que código semelhante existe por aí. Os métodos permitem que você encadeie convenientemente, por exemplo:
Vector v = ...;
v.normalize().negate();
Ou ainda:
Vector v = Vector{1., 2., 3.}.normalize().negate();
Agora, se fornecermos as funções begin () e end (), poderíamos usar nosso Vector em um novo estilo de loop for, digamos, para fazer um loop sobre as 3 coordenadas x, y e z (você pode, sem dúvida, construir exemplos mais "úteis" substituindo Vector por, por exemplo, String):
Vector v = ...;
for (double x : v) { ... }
Podemos até fazer:
Vector v = ...;
for (double x : v.normalize().negate()) { ... }
e também:
for (double x : Vector{1., 2., 3.}) { ... }
No entanto, o seguinte (parece-me) está quebrado:
for (double x : Vector{1., 2., 3.}.normalize()) { ... }
Embora pareça uma combinação lógica dos dois usos anteriores, acho que este último uso cria uma referência pendente, enquanto os dois anteriores são perfeitamente adequados.
- Isso é correto e amplamente apreciado?
- Qual das opções acima é a parte "ruim" que deve ser evitada?
- A linguagem seria melhorada mudando a definição do loop for baseado em intervalo de forma que os temporários construídos na expressão for existissem durante o loop?