Является ли это известной ловушкой C++11 для циклов?

Давайте представим, что у нас есть структура для хранения 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, существовали на протяжении всего цикла?
89
задан iammilind 15 May 2012 в 03:26
поделиться