Представим, что у нас есть структура для хранения 3 двойников с некоторыми функциями-членами:
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;
}
// ...
};
Это немного надумано для простоты, но я уверен, что вы согласны с тем, что похожий код существует. Эти методы позволяют удобно объединить в цепочку, например:
Vector v = ...;
v.normalize().negate();
Или даже:
Vector v = Vector{1., 2., 3.}.normalize().negate();
Теперь, если бы мы предоставили функции begin () и end (), мы могли бы использовать наш вектор в цикле for нового стиля, скажем, чтобы перебрать 3 координаты x, y и z (вы, без сомнения, можете создать больше «полезных» примеров заменив Vector на, например, String):
Vector v = ...;
for (double x : v) { ... }
Мы даже можем:
Vector v = ...;
for (double x : v.normalize().negate()) { ... }
а также:
for (double x : Vector{1., 2., 3.}) { ... }
Однако следующее (как мне кажется) не работает:
for (double x : Vector{1., 2., 3.}.normalize()) { ... }
Хотя это кажется логической комбинацией двух предыдущих использований, я думаю, что последнее использование создает висящую ссылку, в то время как предыдущие два совершенно нормальны.
- Это правильно и широко ли это ценится?
- Какая часть из вышеперечисленного является «плохой», чего следует избегать?
- Можно ли улучшить язык, изменив определение цикла for на основе диапазона таким образом, чтобы временные структуры, созданные в выражении for, существовали в течение всего цикла?