Уявімо, що у нас є структура для проведення 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 (), ми могли б використовувати наш Vector у новому стилі for loop, скажімо, цикл над 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, існували протягом усього циклу?