function template
<utility>

std::move_if_noexcept

template <class T>
  typename conditional < is_nothrow_move_constructible<T>::value ||
                         !is_copy_constructible<T>::value,
                         T&&, const T& >::type move_if_noexcept(T& arg) noexcept;
Move if noexcept
Returns an rvalue reference to arg, unless copying is a better option than moving to provide at least a strong exception guarantee.

The strong guarantee is provided by operations that are guaranteed to leave objects in the same state they were before the operation in the case an exception is thrown. This is achieved either by operating on copies (so that the original object is left intact during the operation), or by using only operations that do not throw (in this case, a higher level of guarantee is provided: nothrow guarantee).

Some operations can be implemented both by moving or by copying objects, generally moving for rvalues and copying for lvalues: Moving is generally a more efficient operation than copying when the object is no longer needed (such as rvalues).

This function selects the type of an argument as an rvalue reference if the type is nothrow move-constructible (i.e., its move constructor never throws), or alternativelly, as an lvalue reference if the type is copy-constructible. If the type is neither, the function returns an rvalue, which will be selected for move-only types (even if they may throw).

The function returns the same as move(arg) but with the return type casted to either T&& or const T&, depending on the properties of T.

Parameters

arg
An object.

Return value

An rvalue reference that refers to arg if T is nothrow move-constructible or if T is not copy-constructible.
An lvalue reference otherwise.
The return type uses conditional to select between two types: T&& and const T&.

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// move_if_noexcept example
#include <utility>      // std::move_if_noexcept
#include <iostream>     // std::cout

// function with lvalue and rvalue reference overloads:
template <class T> void overloaded (T&  x) {std::cout << "[lvalue]\n";}
template <class T> void overloaded (T&& x) {std::cout << "[rvalue]\n";}

struct A {   // copyable + moveable (noexcept)
  A() noexcept {}
  A (const A&) noexcept {}
  A (A&&) noexcept {}
};

struct B {   // copyable + moveable (no noexcept)
  B() {}
  B (const B&) {}
  B (B&&) {}
};

struct C {   // moveable only (no noexcept)
  C() {}
  C (C&&) {}
};

int main () {
  std::cout << "A: "; overloaded (std::move_if_noexcept(A()));
  std::cout << "B: "; overloaded (std::move_if_noexcept(B()));
  std::cout << "C: "; overloaded (std::move_if_noexcept(C()));
  return 0;
}


Output:
A: [rvalue]
B: [lvalue]
C: [rvalue]

Data races

Calling this function introduces no data races.
Although notice that passing the returned value to functions implementing move semantics generally involves modifying the value or validity of the object.

Exceptions

No-throw guarantee: this function never throws exceptions.

See also