This subclause contains some basic function and class templates that are used throughout the rest of the library.
The header <utility> defines several types and function templates that are described in this Clause. It also defines the template pair and various function templates that operate on pair objects.
#include <initializer_list> namespace std { // [operators], operators: namespace rel_ops { template<class T> bool operator!=(const T&, const T&); template<class T> bool operator> (const T&, const T&); template<class T> bool operator<=(const T&, const T&); template<class T> bool operator>=(const T&, const T&); } // [utility.swap], swap: template<class T> void swap(T& a, T& b) noexcept(see below); template <class T, size_t N> void swap(T (&a)[N], T (&b)[N]) noexcept(noexcept(swap(*a, *b))); // [utility.exchange], exchange: template <class T, class U=T> T exchange(T& obj, U&& new_val); // [forward], forward/move: template <class T> constexpr T&& forward(remove_reference_t<T>& t) noexcept; template <class T> constexpr T&& forward(remove_reference_t<T>&& t) noexcept; template <class T> constexpr remove_reference_t<T>&& move(T&&) noexcept; template <class T> constexpr conditional_t< !is_nothrow_move_constructible<T>::value && is_copy_constructible<T>::value, const T&, T&&> move_if_noexcept(T& x) noexcept; // [declval], declval: template <class T> add_rvalue_reference_t<T> declval() noexcept; // as unevaluated operand // [pairs], pairs: template <class T1, class T2> struct pair; // [pairs.spec], pair specialized algorithms: template <class T1, class T2> constexpr bool operator==(const pair<T1,T2>&, const pair<T1,T2>&); template <class T1, class T2> constexpr bool operator< (const pair<T1,T2>&, const pair<T1,T2>&); template <class T1, class T2> constexpr bool operator!=(const pair<T1,T2>&, const pair<T1,T2>&); template <class T1, class T2> constexpr bool operator> (const pair<T1,T2>&, const pair<T1,T2>&); template <class T1, class T2> constexpr bool operator>=(const pair<T1,T2>&, const pair<T1,T2>&); template <class T1, class T2> constexpr bool operator<=(const pair<T1,T2>&, const pair<T1,T2>&); template <class T1, class T2> void swap(pair<T1,T2>& x, pair<T1,T2>& y) noexcept(noexcept(x.swap(y))); template <class T1, class T2> constexpr see below make_pair(T1&&, T2&&); // [pair.astuple], tuple-like access to pair: template <class T> class tuple_size; template <size_t I, class T> class tuple_element; template <class T1, class T2> struct tuple_size<pair<T1, T2> >; template <class T1, class T2> struct tuple_element<0, pair<T1, T2> >; template <class T1, class T2> struct tuple_element<1, pair<T1, T2> >; template<size_t I, class T1, class T2> constexpr tuple_element_t<I, pair<T1, T2>>& get(pair<T1, T2>&) noexcept; template<size_t I, class T1, class T2> constexpr tuple_element_t<I, pair<T1, T2>>&& get(pair<T1, T2>&&) noexcept; template<size_t I, class T1, class T2> constexpr const tuple_element_t<I, pair<T1, T2>>& get(const pair<T1, T2>&) noexcept; template <class T, class U> constexpr T& get(pair<T, U>& p) noexcept; template <class T, class U> constexpr const T& get(const pair<T, U>& p) noexcept; template <class T, class U> constexpr T&& get(pair<T, U>&& p) noexcept; template <class T, class U> constexpr T& get(pair<U, T>& p) noexcept; template <class T, class U> constexpr const T& get(const pair<U, T>& p) noexcept; template <class T, class U> constexpr T&& get(pair<U, T>&& p) noexcept; // [pair.piecewise], pair piecewise construction struct piecewise_construct_t { }; constexpr piecewise_construct_t piecewise_construct{}; template <class... Types> class tuple; // defined in <tuple> // [intseq], Compile-time integer sequences template<class T, T...> struct integer_sequence; template<size_t... I> using index_sequence = integer_sequence<size_t, I...>; template<class T, T N> using make_integer_sequence = integer_sequence<T, see below>; template<size_t N> using make_index_sequence = make_integer_sequence<size_t, N>; template<class... T> using index_sequence_for = make_index_sequence<sizeof...(T)>; }
To avoid redundant definitions of operator!= out of operator== and operators >, <=, and >= out of operator<, the library provides the following:
Requires: Type T is EqualityComparable (Table [equalitycomparable]).
Returns: !(x == y).
template <class T> bool operator>(const T& x, const T& y);
Requires: Type T is LessThanComparable (Table [lessthancomparable]).
Returns: y < x.
template <class T> bool operator<=(const T& x, const T& y);
Requires: Type T is LessThanComparable (Table [lessthancomparable]).
Returns: !(y < x).
template <class T> bool operator>=(const T& x, const T& y);
Requires: Type T is LessThanComparable (Table [lessthancomparable]).
Returns: !(x < y).
In this library, whenever a declaration is provided for an operator!=, operator>, operator>=, or operator<=, and requirements and semantics are not explicitly provided, the requirements and semantics are as specified in this Clause.
template<class T> void swap(T& a, T& b) noexcept(see below);
Remark: The expression inside noexcept is equivalent to:
is_nothrow_move_constructible<T>::value && is_nothrow_move_assignable<T>::value
Requires: Type T shall be MoveConstructible (Table [moveconstructible]) and MoveAssignable (Table [moveassignable]).
Effects: Exchanges values stored in two locations.
template<class T, size_t N>
void swap(T (&a)[N], T (&b)[N]) noexcept(noexcept(swap(*a, *b)));
Requires: a[i] shall be swappable with ([swappable.requirements]) b[i] for all i in the range [0,N).
Effects: swap_ranges(a, a + N, b)
template <class T, class U=T> T exchange(T& obj, U&& new_val);
Effects: Equivalent to:
T old_val = std::move(obj); obj = std::forward<U>(new_val); return old_val;
The library provides templated helper functions to simplify applying move semantics to an lvalue and to simplify the implementation of forwarding functions.
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).
Remark: If the second form is instantiated with an lvalue reference type, the program is ill-formed.
[ 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 }
In the first call to factory, A1 is deduced as int, so 2 is forwarded to A's constructor as an rvalue. In the second call to factory, A1 is deduced as int&, so i is forwarded to A's constructor as an lvalue. In both cases, A2 is deduced as double, so 1.414 is forwarded to A's constructor as an 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&&) }
In the first call to factory, A1 is deduced as A&, so a is forwarded as a non-const lvalue. This binds to the constructor A(const A&), which copies the value from a. In the second call to factory, because of the call std::move(a), A1 is deduced as A, so a is forwarded as an rvalue. This binds to the constructor A(A&&), which moves the value from a.
— end example ]
template <class T> constexpr conditional_t<
!is_nothrow_move_constructible<T>::value && is_copy_constructible<T>::value,
const T&, T&&> move_if_noexcept(T& x) noexcept;
Returns: std::move(x)
The library provides the function template declval to simplify the definition of expressions which occur as unevaluated operands (Clause [expr]).
template <class T>
add_rvalue_reference_t<T> declval() noexcept; // as unevaluated operand
Remarks: If this function is odr-used ([basic.def.odr]), the program is ill-formed.
Remarks: The template parameter T of declval may be an incomplete type.
[ Example:
template <class To, class From> decltype(static_cast<To>(declval<From>())) convert(From&&);
declares a function template convert which only participates in overloading if the type From can be explicitly converted to type To. For another example see class template common_type ([meta.trans.other]). — end example ]