Во время некоторой реализации я застрял с проблемой гарантии безопасности исключений и std::move()
, Я знаю, что ТАК не очень хорошее место, чтобы спросить: «Каково твое мнение?» Boo
) вопрос, но здесь я хотел бы убедиться, что мое понимание верно, и после прочтения этого вопроса, возможно, вы сможете направить меня на правильный путь.
Рассмотрим следующий код:
struct Foo {
using Y = std::vector<std::string>;
using X = std::vector<Y>;
void add (Y y) {
src.push_back (std::move (y)); // (1)
src = process (std::move (src)); // (2)
}
private:
X process (X&& vec) { // (F)
for (auto& v : vec) {
v.resize (10); // (3)
}
return std::move (vec);
}X src;
};
Посмотрите на add()
функция-член, если исключение
выбрасывается из (1) и в соответствии с n4296 [vector.modifiers / 1]
Если исключение выдается при вставке одного элемента в конце и
T
являетсяCopyInsertable
или жеis_nothrow_move_constructible<T>::value
являетсяtrue
Эффектов нет.
тогда сильная гарантия сохраняется, я прав?
Если мы посмотрим на (2), то здесь также может быть сгенерировано исключение, потому что (3) может вызвать исключение. Поправь меня если я не прав
В этой ситуации (2), если я перееду src
к process()
функция-член и исключение выдается из process()
затем src
является
не указано и что означает, что сохраняется только базовая гарантия?
Делать add()
функция члена сильная гарантия, я должен изменить
(2) и (F) соответственно:
src = process (src); // (2)
X process (X vec); // (F)
?
Так что если Foo::src
имеет огромное количество элементов, то делает сильный
гарантия связана с меньшей эффективностью (потому что должна быть сделана дополнительная копия)?
Может быть, уровень гарантии должен быть оставлен на усмотрение пользователя класса, сделав его шаблоном класса, похожим на этот:
struct S {};
struct B {};
template <typename T>
struct Boo {
using Y = std::vector<std::string>;
using X = std::vector<Y>;
void add (Y y) {
src.push_back (std::move (y));
src = process_helper (typename std::is_same<T, S>::type {});
}private:
X process_helper (std::true_type) {
return process (src);
}
X process_helper (std::false_type) {
return process (std::move (src));
}
X process (X vec) {
for (auto& v : vec) {
v.resize (10);
}
return std::move (vec);
}
X src;
};
Это хорошая или плохая идея?
Задача ещё не решена.
Других решений пока нет …