23 General utilities library [utilities]

23.2 Utility components [utility]

23.2.5 Forward/move helpers [forward]

Библиотека предоставляет шаблонные вспомогательные функции, чтобы упростить применение семантики перемещения к lvalue и упростить реализацию функций пересылки. Все функции, указанные в этом подпункте, являются signal-safe ( ).[csignal.syn]

template <class T> constexpr T&& forward(remove_reference_t<T>& t) noexcept; template <class T> constexpr T&& forward(remove_reference_t<T>&& t) noexcept;

Returns: static_­cast<T&&>(t).

Remarks: Если вторая форма создается со ссылочным типом lvalue, программа имеет неправильный формат.

[Example:

template <class T, class A1, class A2>
shared_ptr<T> factory(A1&& a1, A2&& a2) {
  return shared_ptr<T>(new T(std::forward<A1>(a1), std::forward<A2>(a2)));
}

struct A {
  A(int&, const double&);
};

void g() {
  shared_ptr<A> sp1 = factory<A>(2, 1.414); // error: 2 will not bind to int&
  int i = 2;
  shared_ptr<A> sp2 = factory<A>(i, 1.414); // OK
}

При первом вызове factory, A1 выводится как int, поэтому 2 передается Aконструктору как rvalue. Во втором вызове factory, A1 выводится как int&, поэтому i передается Aконструктору как lvalue. В обоих случаях A2 выводится как double, поэтому 1.414 передается Aконструктору как rvalue. ] end example

template <class T> constexpr remove_reference_t<T>&& move(T&& t) noexcept;

Returns: static_­cast<remove_­reference_­t<T>&&>(t).

[Example:

template <class T, class A1>
shared_ptr<T> factory(A1&& a1) {
  return shared_ptr<T>(new T(std::forward<A1>(a1)));
}

struct A {
  A();
  A(const A&);      // copies from lvalues
  A(A&&);           // moves from rvalues
};

void g() {
  A a;
  shared_ptr<A> sp1 = factory<A>(a);                // “a” binds to A(const A&)
  shared_ptr<A> sp1 = factory<A>(std::move(a));     // “a” binds to A(A&&)
}

При первом вызове factory, A1 выводится как A&, поэтому a передается как неконстантное lvalue. Это связывается с конструктором A(const A&), который копирует значение из a. Во втором вызове factory, из - за вызова std​::​move(a), A1 выводится в виде A, так a пересылается как RValue. Это связывается с конструктором A(A&&), который перемещает значение из a. ] end example

template <class T> constexpr conditional_t< !is_nothrow_move_constructible_v<T> && is_copy_constructible_v<T>, const T&, T&&> move_if_noexcept(T& x) noexcept;

Returns: std​::​move(x).