# std::move_if_noexcept

< cpp‎ | utility

定义于头文件 `<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 起)

若参数的移动构造函数不抛异常，则 `move_if_noexcept` 获得到参数的右值引用，否则获得左值引用。它典型地用于组合移动语义和强异常保证。

### 参数

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 << "Throwing move constructor called\n";
        }
        Bad(const Bad&) // 亦可能抛出
        {
            std::cout << "Throwing copy constructor called\n";
        }
    };

    struct Good
    {
        Good() {}
        Good(Good&&) noexcept // 将不抛出
        {
            std::cout << "Non-throwing move constructor called\n";
        }
        Good(const Good&) noexcept // 将不抛出
        {
            std::cout << "Non-throwing copy constructor called\n";
        }
    };

    int main()
    {
        Good g;
        Bad b;
        Good g2 = std::move_if_noexcept(g);
        Bad b2 = std::move_if_noexcept(b);
    }

输出：

    Non-throwing move constructor called
    Throwing copy constructor called

### 复杂度

常数

### 参阅

forward (C++11) | 转发一个函数实参 (函数模板)
move (C++11) | 获得右值引用 (函数模板)