Информация об изменениях

Сообщение Re[10]: Exception safe T Stack::pop() ? от 21.08.2018 14:19

Изменено 21.08.2018 14:21 N. I.

Re[10]: Exception safe T Stack::pop() ?
uzhas:

U>ты хочешь сказать, что из-за того, что в свежем стандарте появилось больше безопасных вариантов вызова метода T pop() проблема как бы исчезла?

U>она не исчезла, т.к. "опасные" варианты всё еще остались.

"Опасные" варианты использования всегда можно придумать, в том числе и для пары top и pop:

T t = std::move(stack.top());
POTENTIALLY_THROWING_EXPRESSION;
use_value(t);
stack.pop();

Если POTENTIALLY_THROWING_EXPRESSION кинет исключение, то на вершине стеке, возможно, останется лежать мусорный объект, а полезное значение топового элемента может быть "утеряно".

U>в стандарте нет таких примеров, что вот вызывайте std::vector::at (для примера) только в одну строчку с присваиванием, иначе мы не даем гарантии на безопасность к исключениям.


Тебе возможные варианты кривого использования std::vector::at привести, что ли?

U>это ерунда какая-то, слишком уж много нюансов надо держать в голове


Мда, это ж какой мегамозг надо иметь, чтоб держать в голове два действия: перемещение/копирование элемента и его удаление... С таким rocket science далеко не каждый справится.

U>что ты скажешь про такие варианты вызова?

U>
void f1(T t);
void f2(const T& t);
void f3(T&& t);

template<typename U>
void f4(U&& t) {}

int main() {
  T t;
  t = stack.pop(); // 1
  f1(stack.pop()); //2
  f2(stack.pop()); //3
  f3(stack.pop()); //4
  f4(stack.pop()); //5
}

U>в каких случаях C++17 нас защищает, а в каких у нас уже будут проблемы при исключениях при копировании?

Если T — это кошерный тип с небросающим перемещающим конструктором и небросающим перемещающим оператором присваивания, то копирования T тут нигде не будет (внутренности f1 — f4 не рассматриваем). В этом случае возможностей C++11 уже достаточно.

В случае, если для возврата значения из pop используется потенциально бросающее копирование, C++17 даёт возможность сделать отложенный вызов деструктора для топового элемента при условии, что исключение брошено не было. Дальше при инициализации параметра t функции f1 C++17 обеспечивает guaranteed copy elision.
Re[10]: Exception safe T Stack::pop() ?
uzhas:

U>ты хочешь сказать, что из-за того, что в свежем стандарте появилось больше безопасных вариантов вызова метода T pop() проблема как бы исчезла?

U>она не исчезла, т.к. "опасные" варианты всё еще остались.

"Опасные" варианты использования всегда можно придумать, в том числе и для пары top и pop:

T t = std::move(stack.top());
POTENTIALLY_THROWING_EXPRESSION;
use_value(t);
stack.pop();

Если POTENTIALLY_THROWING_EXPRESSION кинет исключение, то на вершине стека, возможно, останется лежать мусорный объект, а полезное значение топового элемента может быть "утеряно".

U>в стандарте нет таких примеров, что вот вызывайте std::vector::at (для примера) только в одну строчку с присваиванием, иначе мы не даем гарантии на безопасность к исключениям.


Тебе возможные варианты кривого использования std::vector::at привести, что ли?

U>это ерунда какая-то, слишком уж много нюансов надо держать в голове


Мда, это ж какой мегамозг надо иметь, чтоб держать в голове два действия: перемещение/копирование элемента и его удаление... С таким rocket science далеко не каждый справится.

U>что ты скажешь про такие варианты вызова?

U>
void f1(T t);
void f2(const T& t);
void f3(T&& t);

template<typename U>
void f4(U&& t) {}

int main() {
  T t;
  t = stack.pop(); // 1
  f1(stack.pop()); //2
  f2(stack.pop()); //3
  f3(stack.pop()); //4
  f4(stack.pop()); //5
}

U>в каких случаях C++17 нас защищает, а в каких у нас уже будут проблемы при исключениях при копировании?

Если T — это кошерный тип с небросающим перемещающим конструктором и небросающим перемещающим оператором присваивания, то копирования T тут нигде не будет (внутренности f1 — f4 не рассматриваем). В этом случае возможностей C++11 уже достаточно.

В случае, если для возврата значения из pop используется потенциально бросающее копирование, C++17 даёт возможность сделать отложенный вызов деструктора для топового элемента при условии, что исключение брошено не было. Дальше при инициализации параметра t функции f1 C++17 обеспечивает guaranteed copy elision.