На днях столкнулся с особенностью std::exchange.
Как оказывается функция не является noexcept, а почему использовать её в конструкторе перемещения нельзя.
Очевидно напрашивается написать свой аналог exchange_no_except.
Почему об этом не подумали в стандарте и как пишете вы ?
Здравствуйте, _NN_, Вы писали:
_NN>На днях столкнулся с особенностью std::exchange. _NN>Как оказывается функция не является noexcept, а почему использовать её в конструкторе перемещения нельзя.
а почему нельзя? Если вы уверены, что функция не бросит исключение, вы её вполне можете использовать в деструкторах, перемещающих конструкторах и пр. не обращая внимание есть ли там noexcept, или нет.
_NN>Очевидно напрашивается написать свой аналог exchange_no_except.
std::swap? Вообще, вопрос звучит так, как будто вам нужен именно swap.
_NN>Почему об этом не подумали в стандарте и как пишете вы ?
наверное потому что std::exchange может внутри делать копирование. И тогда noexcept точно не поставишь. Можно было бы извращаться, написать кучу перегрузок и в каких-то случаях поставить вожделенный noexcept, но подозреваю что не очень то и надо.
std::string some_value, new_value;
auto old_value = std::exchange(some_value, new_value); // вот тут может быть брошено исключение
Здравствуйте, sergii.p, Вы писали:
SP>Здравствуйте, _NN_, Вы писали:
_NN>>На днях столкнулся с особенностью std::exchange. _NN>>Как оказывается функция не является noexcept, а почему использовать её в конструкторе перемещения нельзя.
SP>а почему нельзя? Если вы уверены, что функция не бросит исключение, вы её вполне можете использовать в деструкторах, перемещающих конструкторах и пр. не обращая внимание есть ли там noexcept, или нет.
Можно то можно но хотелось бы гарантии по строже чем уверенность.
К тому же статические анализатора кода недовольны
_NN>>Очевидно напрашивается написать свой аналог exchange_no_except.
SP>std::swap? Вообще, вопрос звучит так, как будто вам нужен именно swap.
Exhanhe это не Swap. Иначе не делали бы дополнительную функцию.
_NN>>Почему об этом не подумали в стандарте и как пишете вы ?
SP>наверное потому что std::exchange может внутри делать копирование. И тогда noexcept точно не поставишь. Можно было бы извращаться, написать кучу перегрузок и в каких-то случаях поставить вожделенный noexcept, но подозреваю что не очень то и надо.
Может. Я использую exchange для простых типов вроде указателей чтобы сразу и забрать значение и обнулить .
SP>
SP>std::string some_value, new_value;
SP>auto old_value = std::exchange(some_value, new_value); // вот тут может быть брошено исключение
SP>
struct A
{
std::string s;
int k;
A() : s("test"), k(-1) { }
A(const A& o) : s(o.s), k(o.k) { std::cout << "move failed!\n"; }
A(A&& o) noexcept :
s(std::move(o.s)), // explicit move of a member of class type
k(std::exchange(o.k, 0)) // explicit move of a member of non-class type
{ }
};
Здравствуйте, _NN_, Вы писали:
_NN>Как оказывается функция не является noexcept, а почему использовать её в конструкторе перемещения нельзя.
Можно, так как в конструкторе перемещения аргумент по определению получается по rvalue reference, а единственно место где может возникнуть исключение (конечно при разумной реализации) это:
template<class T, class U = T>
T exchange(T& obj, U&& new_value)
{
T old_value = std::move(obj);
obj = std::forward<U>(new_value);// Вот тут может возникнуть исключение только если obj решит копировать new_value, например если std::forward разрешится в const U&.return old_value;
}
Но именно в конструкторе перемещения U&& всегда будет rvalue reference, и здесь всегда будет перемещение, без копирования.
_NN>Почему об этом не подумали в стандарте и как пишете вы ?
Скорее всего, как всегда, это очередная попытка сделать универсальный швейцарский нож на все случаи жизни (используемый не только в конструкторе перемещения).
Здравствуйте, Videoman, Вы писали:
_NN>>Почему об этом не подумали в стандарте и как пишете вы ? V>Скорее всего, как всегда, это очередная попытка сделать универсальный швейцарский нож на все случаи жизни (используемый не только в конструкторе перемещения).
Технически можно было бы объявить exchange как noexcept если move + forward тоже noexcept.