std::move_if_noexcept
| Определено в заголовочном файле <utility>
|
||
template< class T > typename std::conditional< !std::is_nothrow_move_constructible<T>::value && std::is_copy_constructible<T>::value, const T&, T&& >::type move_if_noexcept(T& x) noexcept; |
(начиная с C++11) (до C++14) |
|
template< class T > constexpr typename std::conditional< !std::is_nothrow_move_constructible<T>::value && std::is_copy_constructible<T>::value, const T&, T&& >::type move_if_noexcept(T& x) noexcept; |
(начиная с C++14) | |
std::move_if_noexcept получает ссылку rvalue на свой аргумент, если его конструктор перемещения не генерирует исключений или если конструктор копирования отсутствует (тип только для перемещения), иначе получает ссылку lvalue на свой аргумент. Обычно она используется для объединения семантики перемещения с надёжной гарантией исключений.
Параметры
| x | — | объект, который нужно переместить или скопировать |
Возвращаемое значение
std::move(x) или x, в зависимости от гарантий исключений.
Сложность
Константная
Примечание
Это используется, например, std::vector::resize, которому может потребоваться выделить новое хранилище, а затем переместить или скопировать элементы из старого хранилища в новое хранилище. Если во время этой операции возникает исключение, std::vector::resize отменяет всё, что было сделано до этого момента, что возможно только в том случае, если std::move_if_noexcept использовалась для принятия решения о том, следует ли использовать конструктор перемещения или конструктор копирования. (если конструктор копирования недоступен, в этом случае конструктор перемещения используется в любом случае, и сильная гарантия исключения может быть отменена)
Пример
#include <iostream>
#include <utility>
struct Bad
{
Bad() {}
Bad(Bad&&) // может сгенерировать исключение
{
std::cout << "Вызывается конструктор перемещения, генерирующий исключение\n";
}
Bad(const Bad&) // тоже может сгенерировать исключение
{
std::cout << "Вызывается конструктор копирования, генерирующий исключение\n";
}
};
struct Good
{
Good() {}
Good(Good&&) noexcept // НЕ будет генерировать исключение
{
std::cout << "Вызывается конструктор перемещения, не генерирующий исключение\n";
}
Good(const Good&) noexcept // НЕ будет генерировать исключение
{
std::cout << "Вызывается конструктор копирования, не генерирующий исключение\n";
}
};
int main()
{
Good g;
Bad b;
[[maybe_unused]] Good g2 = std::move_if_noexcept(g);
[[maybe_unused]] Bad b2 = std::move_if_noexcept(b);
}
Вывод:
Вызывается конструктор перемещения, не генерирующий исключение
Вызывается конструктор копирования, генерирующий исключение
Смотрите также
(C++11) |
пересылает аргумент функции (шаблон функции) |
(C++11) |
получает ссылку на rvalue (шаблон функции) |