[forward] # 22 General utilities library [[utilities]](./#utilities) ## 22.2 Utility components [[utility]](utility#forward) ### 22.2.4 Forward/move helpers [forward] [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L328) The library provides templated helper functions to simplify applying move semantics to an lvalue and to simplify the implementation of forwarding functions[.](#1.sentence-1) All functions specified in this subclause are [signal-safe](support.signal#def:evaluation,signal-safe "17.14.5 Signal handlers [support.signal]")[.](#1.sentence-2) [🔗](#lib:forward) `template constexpr T&& forward(remove_reference_t& t) noexcept; template constexpr T&& forward(remove_reference_t&& t) noexcept; ` [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L345) *Mandates*: For the second overload, is_lvalue_reference_v is false[.](#2.sentence-1) [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L349) *Returns*: static_cast(t)[.](#3.sentence-1) [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L353) [*Example [1](#example-1)*: template shared_ptr factory(A1&& a1, A2&& a2) {return shared_ptr(new T(std::forward(a1), std::forward(a2)));}struct A { A(int&, const double&);}; void g() { shared_ptr sp1 = factory(2, 1.414); // error: 2 will not bind to int&int i = 2; shared_ptr sp2 = factory(i, 1.414); // OK} In the first call to factory,A1 is deduced as int, so 2 is forwarded to A's constructor as an rvalue[.](#4.sentence-1) In the second call to factory,A1 is deduced as int&, so i is forwarded to A's constructor as an lvalue[.](#4.sentence-2) In both cases, A2 is deduced as double, so 1.414 is forwarded to A's constructor as an rvalue[.](#4.sentence-3) — *end example*] [🔗](#lib:forward_like) `template constexpr auto forward_like(U&& x) noexcept -> see below; ` [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L389) *Mandates*: T is a referenceable type ([[defns.referenceable]](defns.referenceable "3.45 referenceable type"))[.](#5.sentence-1) [6](#6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L393) - [(6.1)](#6.1) Let *COPY_CONST*(A, B) be const B if A is a const type, otherwise B[.](#6.1.sentence-1) - [(6.2)](#6.2) Let *OVERRIDE_REF*(A, B) be remove_reference_t&& if A is an rvalue reference type, otherwise B&[.](#6.2.sentence-1) - [(6.3)](#6.3) Let V be*OVERRIDE_REF*(T&&, *COPY_CONST*(remove_reference_t, remove_reference_t)) [7](#7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L408) *Returns*: static_cast(x)[.](#7.sentence-1) [8](#8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L412) *Remarks*: The return type is V[.](#8.sentence-1) [9](#9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L416) [*Example [2](#example-2)*: struct accessor { vector* container; decltype(auto) operator[](this auto&& self, size_t i) {return std::forward_like((*container)[i]); }};void g() { vector v{"a"s, "b"s}; accessor a{&v}; string& x = a[0]; // OK, binds to lvalue reference string&& y = std::move(a)[0]; // OK, is rvalue reference string const&& z = std::move(as_const(a))[1]; // OK, is const&& string& w = as_const(a)[1]; // error: will not bind to non-const} — *end example*] [🔗](#lib:move,function) `template constexpr remove_reference_t&& move(T&& t) noexcept; ` [10](#10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L444) *Returns*: static_cast&&>(t)[.](#10.sentence-1) [11](#11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L448) [*Example [3](#example-3)*: template shared_ptr factory(A1&& a1) {return shared_ptr(new T(std::forward(a1)));}struct A { A(); A(const A&); // copies from lvalues A(A&&); // moves from rvalues}; void g() { A a; shared_ptr sp1 = factory(a); // “a'' binds to A(const A&) shared_ptr sp2 = factory(std::move(a)); // “a'' binds to A(A&&)} In the first call to factory,A1 is deduced as A&, so a is forwarded as a non-const lvalue[.](#11.sentence-1) This binds to the constructor A(const A&), which copies the value from a[.](#11.sentence-2) In the second call to factory, because of the callstd​::​move(a),A1 is deduced as A, so a is forwarded as an rvalue[.](#11.sentence-3) This binds to the constructor A(A&&), which moves the value from a[.](#11.sentence-4) — *end example*] [🔗](#lib:move_if_noexcept) `template constexpr conditional_t< !is_nothrow_move_constructible_v && is_copy_constructible_v, const T&, T&&> move_if_noexcept(T& x) noexcept; ` [12](#12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L488) *Returns*: std​::​move(x)[.](#12.sentence-1)