20.1 概览
- 这个条款描述了在C++程序中广泛使用的工具;一些用于C++标准库的其他元素.
20.2 Utility components
这个副条款包含了一些用于库的其余部分的基础函数和类模板.
头文件<utility> 概要
头文件<utility>定义在这个条款里描述的若干类型和函数模板. 它也定义the template pair和大量用于pair对象操作的函数模板.
#include <initializer_list> namespace std { // 运算符: 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&); } // swap: template <class T> constexpr void swap(T& a, T& b) noexcept(/* 见定义 */ ); template <class T, size_t N> constexpr void swap(T (&a)[N], T (&b)[N]) noexcept(is_nothrow_swappable_v<T>); // exchange: template <class T, class U=T> T exchange(T& obj, U&& new_val); // 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_v<T> && is_copy_constructible_v<T>, const T&, T&&> move_if_noexcept(T& x) noexcept; // as_const : template <class T> constexpr add_const_t<T>& as_const(T& t) noexcept; template <class T> void as_const(const T&&) = delete; // declval: template <class T> add_rvalue_reference_t<T> declval() noexcept; // 作为不求值操作数 // 编译时整数数列 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, /* 见定义 */ >; 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)>; // pair: template <class T1, class T2> struct pair; // 对 pair 特化的算法: 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> constexpr void swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y))); template <class T1, class T2> constexpr /* 见定义 */ make_pair(T1&&, T2&&); // 对 pair 的 tuple 式访问: 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<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 const T&& get(const 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; template <class T, class U> constexpr const T&& get(const pair<U, T>&& p) noexcept; // pair 逐段构造 struct piecewise_construct_t { }; constexpr piecewise_construct_t piecewise_construct{}; template <class... Types> class tuple; // 定义于 <tuple> }
20.2.1 运算符
1.为了避免多余定义, !=用==, >,<=和>=使用<.
template <class T> bool operator!=(const T& x, const T& y);
2.要求: T是EqualityComparable.
3.返回值: !(x==y).
template <class T> bool operator>(const T& x, const T& y);
4.要求: T是LessThanComparable.
5.返回值: y<x
template <class T> bool operator<=(const T& x, const T& y);
6.要求: T是LessThanComparable.
7.返回值: !(y<x)
template <class T> bool operator>=(const T& x, const T& y);
8.要求: T是LessThanComparable.
9.返回值: !(x<y)
10.在这个库, 每当对 != , > , >= , <= 进行声明时, 并且未显示提供要求和语义, 则要求和语义均在像本条款中指定的.
20.2.2 swap
template<class T> void swap(T& a, T& b) noexcept(see below);
1.备注: noexcept里的表达式等价于:
is_nothrow_move_constructible<T>::value && is_nothrow_move_assignable<T>::value
2.要求: T应该是MoveConstructible和MoveAssignable.
3.作用: 交换保存在两个位置的值.
template<class T, size_t N>
void swap(T (&a)[N], T (&b)[N]) noexcept(noexcept(swap(*a, *b)));
4.要求: 对于[0,N]内的所有i, a[i]应可与b[i]交换.
5.作用: swap_ranges(a,a+N,b)
20.2.3 forward/move helpers
1.该库提供了模板化的(helper)函数, 以简化将移动语义应用于左值并简化转发功能的实现.
template <class T> T&& forward(typename remove_reference<T>::type& t) noexcept;
template <class T> T&& forward(typename remove_reference<T>::type&& t) noexcept;
2.返回值: static_cast<T&&>(t)
3.如果第二个形式被一个左值引用实例化, 程序ill-formed.
4.[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 }
5.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 note ]
6.[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&&) }
7.In the first call to factory, A1 is deduced as A&, so a is forwarded as a non-const lvalue. This binds to theconstructor 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 note ]
template <class T> typename conditional<
!is_nothrow_move_constructible<T>::value && is_copy_constructible<T>::value,
const T&, T&&>::type move_if_noexcept(T& x) noexcept;
8.返回值: std::move(x)
20.2.4 函数模板declval
1.该库提供函数模板declval,以简化对未求值运算符中出现的表达式的定义.
template <class T>
typename add_rvalue_reference<T>::type declval() noexcept; // as unevaluated operand
2.备注: 如果这个函数被odr式使用, 程序ill-formed
3.备注: declval的模板参数T可能是未完成类型.
[Example:
template <class To, class From> decltype(static_cast<To>(declval<From>())) convert(From&&);
声明一个函数模板convert,仅当From类型可以显式转换为To类型时, 该转换才参与重载. 有关另一个示例, 请参见类模板common_type. -end note ]
20.3 Pairs
for align
20.3.1 概览
1.该库为合成值对提供了模板. 该库还提供了一个匹配功能模板以简化其构造, 并提供了多个模板, 这些模板可以访问pair对象, 就像它们是tuple对象一样.
20.3.2 类模板pair
// defined in header <utility> namespace std { template <class T1, class T2> struct pair { typedef T1 first_type; typedef T2 second_type; T1 first; T2 second; pair(const pair&) = default; pair(pair&&) = default; constexpr pair(); pair(const T1& x, const T2& y); template<class U, class V> pair(U&& x, V&& y); template<class U, class V> pair(const pair<U, V>& p); template<class U, class V> pair(pair<U, V>&& p); template <class... Args1, class... Args2> pair(piecewise_construct_t, tuple<Args1...> first_args, tuple<Args2...> second_args); pair& operator=(const pair& p); template<class U, class V> pair& operator=(const pair<U, V>& p); pair& operator=(pair&& p) noexcept(see below); template<class U, class V> pair& operator=(pair<U, V>&& p); void swap(pair& p) noexcept(see below); }; }
1.构造函数和pair成员函数不会抛出异常, 除非指定的对此操作调用的元素抛出异常.
constexpr pair();
2.要求: is_default_constructible<first_type>::value 是 true and is_default_constructible<second_type>::value 是 true.
3.作用: 值初始化first和second.
pair(const T1& x, const T2& y);
4.要求: is_copy_constructible<first_type>::value 是 true and is_copy_constructible<second_type>::value 是 true.
5.作用: 这个构造函数用x初始化first, 用y初始化second.
template<class U, class V> pair(U&& x, V&& y);
6.要求: is_constructible<first_type, U&&>::value 是 true and is_constructible<second_type, V&&>::value 是 true.
7.作用: 这个构造函数用std::forward<U>(x)初始化first, 用std::forward<V>(y)初始化second.
8.备注: 如果U不是隐式可转换到first_type或V不是隐式可转换到second_type的, 这个构造函数不得参与重载决议.
template<class U, class V> pair(const pair<U, V>& p);
9.要求: is_constructible<first_type, const U&>::value 是 true and is_constructible<second_type, const V&>::value 是 true.
10.作用: 从参数对应的成员中初始化.
11.备注: 如果U不是隐式可转换到first_type或V不是隐式可转换到second_type的, 这个构造函数不得参与重载决议.
template<class U, class V> pair(pair<U, V>&& p);
12.要求: is_constructible<first_type, U&&>::value 是 true and is_constructible<second_type, V&&>::value 是 true.
13.作用: 让std::forward<U>(p.first)初始化first, std::forward<V>(p.second)初始化second.
14.备注: 如果U不是隐式可转换到first_type或V不是隐式可转换到second_type的, 这个构造函数不得参与重载决议.
template<class... Args1, class... Args2>
pair(piecewise_construct_t, tuple<Args1...> first_args, tuple<Args2...> second_args);
15.要求: is_constructible<first_type, Args1&&...>::value 是 true and is_constructible<second_type, Args2&&...>::value 是 true.
16.作用: 让通过转发first_args获得的Args1...类型的参数初始化first,通过转发fsecond_args获得的Args2...类型的参数初始化second. 这里, 转发类型U的一个元素x在tuple对象内意味着调用std::forward<U>(x). 这个形式的构造函数, 第一和第二个参数分别在单独的tuple对象中提供, 称为分段构造.
pair& operator=(const pair& p);
17.要求: is_copy_assignable<first_type>::value 是 true and is_copy_assignable<second_type>::value 是 true.
18.作用: 用p.first对first赋值, p.second对second.
19.返回值: *this.
template<class U, class V> pair& operator=(const pair<U, V>& p);
20.要求: is_assignable<first_type&, const U&>::value 是 true and is_assignable<second_type&, const V&>::value 是 true.
21.作用: 同上
22.返回值: 同上
pair& operator=(pair&& p) noexcept(see below);
23.备注: noexcept里的表达式等价于
is_nothrow_move_assignable<T1>::value && is_nothrow_move_assignable<T2>::value
24.要求: is_move_assignable<first_type>::value is true and is_move_assignable<second_type>::value is true.
25.作用: 用std::forward<first_type>(p.first)对first赋值, std::forward<second_type>(p.second)对second赋值.
26.返回值: *this
template<class U, class V> pair& operator=(pair<U, V>&& p);
27.要求: is_assignable<first_type&, U&&>::value is true and is_assignable<second_type&, V&&>::value is true.
28.作用: 用std::forward<U>(p.first)对first赋值, std::forward<V>(p.second)对second赋值.
29.返回值: *this
void swap(pair& p) noexcept(see below);
30.备注: noexcept里的表达式等价于
noexcept(swap(first, p.first)) && noexcept(swap(second, p.second))
31.要求: first和p.first可交换, second和p.second可交换.
32.作用: 交换first和p.first, second和p.second.
20.3.3 特化算法(Specialized algorithms)
template <class T1, class T2>
bool operator==(const pair<T1, T2>& x, const pair<T1, T2>& y);
1.返回值: x.first == y.first && x.second == y.second.
template <class T1, class T2>
bool operator<(const pair<T1, T2>& x, const pair<T1, T2>& y);
2.返回值: x.first < y.first || (!(y.first < x.first) && x.second < y.second )
剩下的和20.2.1/20.2.2要求一样
template<class T1, class T2>
pair<V1, V2> make_pair(T1&& x, T2&& y);
8.返回值: pair<V1, V2>(std::forward<T1>(x), std::forward<T2>(y));
V1和V2这样确定: 令每个Ui为每个Ti的decay<Ti>::type.如果Ui等于reference_wrapper<X>, 令每个Vi是X&, 否则Vi是Ui. (Let Ui be decay<Ti>::type for each Ti. Then each Vi is X& if Ui equals reference_wrapper<X>, otherwise Vi is Ui.)
9.[Example: 替代:
return pair<int, double>(5,3.1415926); // 隐式类型
一个C++程序可能contain:
return make_pair(5, 3.1415926); // 类型推断
-end example]
20.3.4 像tuple访问pair
tuple_size<pair<T1, T2> >::value
1.返回值: 整数常量表达式.
2.值: 2
tuple_element<0, pair<T1, T2> >::type
3.值: 类型T1
tuple_element<1, pair<T1, T2> >::type
4.值: 类型T2
template<size_t I, class T1, class T2> typename tuple_element<I, std::pair<T1, T2> >::type& get(pair<T1, T2>&) noexcept; template<size_t I, class T1, class T2> const typename tuple_element<I, std::pair<T1, T2> >::type& get(const pair<T1, T2>&) noexcept;
5.返回值: 如果 I == 0 返回p.first;如果 I == 1 返回p.second;否则程序ill-formed.
template<size_t I, class T1, class T2> typename tuple_element<I, std::pair<T1, T2> >::type&& get(std::pair<T1, T2>&&) noexcept;
6.返回值: 如果 I == 0 返回std::forward<T1&&>(p1.first);如果 I == 1 返回std::forward<T2&&>(p.second); 否则程序ill-formed.
20.3.5 分段构造(Piecewise construction)
struct piecewise_construct_t { };
constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t();
1.piecewise_construct_t是个空的结构体类型, 用作独特的类型来消除构造函数和函数重载的歧义. 具体来说, pair具有一个piecewise_construct_t作为第一参数的构造函数, 随后是两个被用于pair对象的元素的分段构造的tuple元素
20.4
for align
20.4.1 概览
1.本小节描述了提供tuple类型的tuple库, 该tuple类型可以作为可以使用任意数量的参数实例化的类模板tuple. 每个模板参数指定tuple中元素的类型.因此, tuple是异构的固定大小的值集合. 具有两个参数的tuple的实例化与具有相同两个参数的pair的实例化相似.见20.3.
2.头文件 <tuple> 概要
namespace std { // 20.4.2, class template tuple: template <class... Types> class tuple; // 20.4.2.4, tuple creation functions: const unspecified ignore; template <class... Types> tuple<VTypes...> make_tuple(Types&&...); template <class... Types> tuple<Types...> forward_as_tuple(Types&&...) noexcept; template<class... Types> tuple<Types&...> tie(Types&...) noexcept; template <class... Tuples> tuple<Ctypes...> tuple_cat(Tuples&&...); // 20.4.2.5, tuple helper classes: template <class T> class tuple_size; // undefined template <class T> class tuple_size<const T>; template <class T> class tuple_size<volatile T>; template <class T> class tuple_size<const volatile T> template <class... Types> class tuple_size<tuple<Types...> >; template <size_t I, class T> class tuple_element; // undefined template <size_t I, class T> class tuple_element<I, const T>; template <size_t I, class T> class tuple_element<I, volatile T>; template <size_t I, class T> class tuple_element<I, const volatile T>; template <size_t I, class... Types> class tuple_element<I, tuple<Types...> >; // 20.4.2.6, element access: template <size_t I, class... Types> typename tuple_element<I, tuple<Types...> >::type& get(tuple<Types...>&) noexcept; template <size_t I, class... types> typename tuple_element<I, tuple<Types...> >::type&& get(tuple<Types...>&&) noexcept; template <size_t I, class... types> typename tuple_element<I, tuple<Types...> >::type const& get(const tuple<Types...>&) noexcept; // 20.4.2.7, relational operators: template<class... TTypes, class... UTypes> bool operator==(const tuple<TTypes...>&, const tuple<UTypes...>&); template<class... TTypes, class... UTypes> bool operator<(const tuple<TTypes...>&, const tuple<UTypes...>&); template<class... TTypes, class... UTypes> bool operator!=(const tuple<TTypes...>&, const tuple<UTypes...>&); template<class... TTypes, class... UTypes> bool operator>(const tuple<TTypes...>&, const tuple<UTypes...>&); template<class... TTypes, class... UTypes> bool operator<=(const tuple<TTypes...>&, const tuple<UTypes...>&); template<class... TTypes, class... UTypes> bool operator>=(const tuple<TTypes...>&, const tuple<UTypes...>&); // 20.4.2.8, allocator-related traits template <class... Types, class Alloc> struct uses_allocator<tuple<Types...>, Alloc>; // 20.4.2.9, specialized algorithms: template <class... Types> void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below); }
20.4.2 类模板tuple
namespace std { template <class... Types> class tuple { public: // 20.4.2.1, tuple construction constexpr tuple(); explicit tuple(const Types&...); template <class... UTypes> explicit tuple(UTypes&&...); tuple(const tuple&) = default; tuple(tuple&&) = default; template <class... UTypes> tuple(const tuple<UTypes...>&); template <class... UTypes> tuple(tuple<UTypes...>&&); template <class U1, class U2> tuple(const pair<U1, U2>&); // iff sizeof...(Types) == 2 template <class U1, class U2> tuple(pair<U1, U2>&&); // iff sizeof...(Types) == 2 // allocator-extended constructors template <class Alloc> tuple(allocator_arg_t, const Alloc& a); template <class Alloc> tuple(allocator_arg_t, const Alloc& a, const Types&...); template <class Alloc, class... UTypes> tuple(allocator_arg_t, const Alloc& a, const UTypes&&...); template <class Alloc> tuple(allocator_arg_t, const Alloc& a, const tuple&); template <class Alloc> tuple(allocator_arg_t, const Alloc& a, tuple&&); template <class Alloc, class... UTypes> tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&); template <class Alloc, class... UTypes> tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&); template <class Alloc, class U1, class U2> tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&); template <class Alloc, class U1, class U2> tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&); // 20.4.2.2, tuple assignment tuple& operator=(const tuple&); tuple& operator=(tuple&&) noexcept(see below); template <class... UTypes> tuple& operator=(const tuple<UTypes...>&); template <class... UTypes> tuple& operator=(tuple<UTypes...>&&); template <class U1, class U2> tuple& operator=(const pair<U1, U2>&); // iff sizeof...(Types) == 2 template <class U1, class U2> tuple& operator=(pair<U1, U2>&&) noexcept; // iff sizeof...(Types) == 2 // 20.4.2.3, tuple swap void swap(tuple&) noexcept(see below); }; }
20.4.2.1 构造函数
1.对每个构造函数来说, 仅在Types中的一个类型构造函数中抛出异常.
2.In the constructor descriptions that follow, let i be in the range [0,sizeof...(Types)) in order, Ti be the ith type in Types, and Ui be the ith type in a template parameter pack named UTypes, where indexing is zero-based.
constexpr tuple();
3.要求: 每个i, is_default_constructible<Ti>::value 是true.
4.作用: 值初始化每个元素.
explicit tuple(const Types&...);
5.要求: 每个i, is_copy_constructible<Ti>::value 是true.
6.作用: 使用相应的参数初始化每个元素.
template <class... UTypes> explicit tuple(UTypes&&... u);
7.要求: sizeof...(Types)==sizeof...(UTypes). is_constructible<Ti, Ui&&>::value is true for all i.
8.作用: 用在std::forward<UTypes>(u)中的相应的值初始化tuple中的每个元素.
9.备注: 这个构造函数不参与重载决议, 除非每个UTypes中的类型可以隐式转换成在Types中对应的类型.
tuple(const tuple& u) = default;
10.要求: 每个i, is_copy_constructible<Ti>::value 是true.
11.作用: 用对应的u的元素初始化每个*this的元素
tuple(tuple&& u) = default;
12.要求: 每个i, is_move_constructible<Ti>::value 是true.
13.作用: For all i, initializes the ith element of *this with std::forward<Ti>(get<i>(u)).
template <class... UTypes> tuple(const tuple<UTypes...>& u);
14.要求: sizeof...(Types) == sizeof...(UTypes). is_constructible<Ti, const Ui&>::value is true for all i.
15.作用: 用对应的u的元素构造每个*this的元素
16.备注: 这个构造函数不参与重载决议, 除非每个i, const Ui&可以隐式转换到Ti.
template <class... UTypes> tuple(tuple<UTypes...>&& u);
17.要求: sizeof...(Types)==sizeof...(UTypes). is_constructible<Ti, Ui&&>::value is true for all i.
18.作用: 对全部i, std::forward<Ui>(get<i>(u))用初始化*this的第i个元素.
19.备注: 这个构造函数不参与重载决议, 除非UTypes的每个类型可以隐式转换从在Types中对应的类型.
template <class U1, class U2> tuple(const pair<U1, U2>& u);
20.要求: sizeof...(Types) == 2. 对第一个类型T0来说, is_constructible<T0, const U1&>::value 是true, 对第二个类型T1来说, is_constructible<T1, const U2&>::value 是true
21.作用: 用u.first构造第一个元素, u.second构造第二个元素.
22.备注: 这个构造函数不参加重载决议, 除非const U1& 可隐式转换到T0, const U2& 可隐式转换到T1.
template <class U1, class U2> tuple(pair<U1, U2>&& u);
23.要求: sizeof...(Types) == 2. 对第一个类型T0来说, is_constructible<T0, U1&&>::value 是true, 对第二个类型T1来说, is_constructible<T1, U2&&>::value 是true.
24.作用: 用std::forward<U1>(u.first)初始化第一个元素, std::forward<U2>(u.second)初始化第二个元素.
25.备注: 这个构造函数不参与重载决议, 除非U1可隐式转换到T0, U2可隐式转换到T1.
template <class Alloc> tuple(allocator_arg_t, const Alloc& a); template <class Alloc> tuple(allocator_arg_t, const Alloc& a, const Types&...); template <class Alloc, class... UTypes> tuple(allocator_arg_t, const Alloc& a, const UTypes&&...); template <class Alloc> tuple(allocator_arg_t, const Alloc& a, const tuple&); template <class Alloc> tuple(allocator_arg_t, const Alloc& a, tuple&&); template <class Alloc, class... UTypes> tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&); template <class Alloc, class... UTypes> tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&); template <class Alloc, class U1, class U2> tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&); template <class Alloc, class U1, class U2> tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
26.要求: Alloc应该满足Allocator(17.6.3.5)的要求.
27.作用: 等价于前面的构造函数, 不同之处在于每个元素都是使用uses_allocator(?)构造的.
20.4.2.2 赋值(Assignment)
1.对于每个tuple赋值运算符, 仅当Types中的一种类型的赋值引发异常时, 才会引发异常. 在下面的函数描述中, 按顺序让i在[0, sizeof ...(Types))范围内, Ti是Types中的第i个类型, Ui是名为UTypes的模板参数包中的第i个类型, 其中, index是从0开始的.
tuple& operator=(const tuple& u);
2.要求: 每个i, is_copy_assignable<Ti>::value 是true.
3.作用: 令每个u的元素赋值给对应的*this的元素.
4.返回值: *this
tuple& operator=(tuple&& u) noexcept(see below);
5.备注: noexcept里的表达式等价于下面表达式的logical AND:
is_nothrow_move_assignable<Ti>::value
Ti是Types里的第i个类型.
6.要求: 每个i, is_move_assignable<Ti>::value 是true.
7.作用: 对于全部的i,令std::forward<Ti>(get<i>(u))赋值给get<i>(*this).
8.返回值: *this.
template <class... UTypes> tuple& operator=(const tuple<UTypes...>& u);
9.要求: sizeof...(Types) == sizeof...(UTypes). 每个i, is_assignable<Ti&,const Ui&>::value是true.
10.作用: 令每个u的元素赋值给对应的*this的元素.
11.返回值: *this
template <class... UTypes> tuple& operator=(tuple<UTypes...>&& u);
12.要求: 每个i, is_assignable<Ti&, Ui&&>::value == true. sizeof...(Types) == sizeof...(UTypes).
13.作用: 每个i, 令std::forward<Ui>(get<i>(u))赋值给get<i>(*this).
14.返回值: *this.
template <class U1, class U2> tuple& operator=(const pair<U1, U2>& u);
15.要求: sizeof...(Types) == 2. 对第一个类型T0来说, is_assignable<T0&, const U1&>::value 是true. 对第二个类型T1来说, is_assignable<T1&, const U2&>::value 是true.
16.作用: 令u.first赋值给this的第一个元素, u.second赋值给 this的第二个元素
17.返回值: *this
template <class U1, class U2> tuple& operator=(pair<U1, U2>&& u);
18.要求: sizeof...(Types) == 2. 对第一个类型T0来说, is_assignable<T0&, U2&&>::value 是true. 对第二个类型T1来说, is_assignable<T1&, U2&&>::value 是true.
19.作用: 令std::forward<U1>(u.first)赋值给this的第一个元素, std::forward<U2>(u.second)赋值给 this的第二个元素.
20.返回值: *this
20.4.2.3 swap
void swap(tuple& rhs) noexcept(see below);
1.备注: noexcept里的表达式等价于下面表达式的logical:
noexcept(swap(declval<Ti&>>(), declval<Ti&>()))
Ti是Types里的第i个类型.
2.要求: 每个*this里的元素应该和rhs对应的元素可交换
3.作用: 对*this的每个元素和rhs中相应的元素调用swap
4.Throws: 无除非一个逐元素swap调用抛出异常.
20.4.2.4 创建tuple函数(Tuple creation functions)
1.在下面的函数描述中, 按顺序让i在[0, sizeof ...(TTypes))范围内, 并让Ti为名为TTypes的模板参数包中的第i个类型;让j按顺序在[0, sizeof ...(UTypes))范围内, 并且Uj是名为UTypes的模板参数包中的第j个类型, 其中index从0开始.
template<class... Types>
tuple<VTypes...> make_tuple(Types&&... t);
2.每个i, Ui是decay<Ti>::type.如果Ui等价于reference_wrapper<X>,VTypes的每个Vi是X&, 否则Vi是Ui.
3.返回值: tuple<VTypes...>(std::forward<Types>(t)...)
4.[Example:
int i; float j; make_tuple(i,ref(i),cref(j)) 创建一个如下类型的tuple tuple<int, int&, const float&>
-end example ]
template<class... Types>
tuple<Types&&...> forward_as_tuple(Types&&... t) noexcept;
5.作用: 构造引用t中参数的tuple,这些参数可以被转发到一个函数. 由于返回值可能引用临时对象,程序应保证该返回值不会超过任何参数.
6.返回值: tuple<Types&& ...>(std::forward<Types>(t)...).
template<class... Types>
tuple<Types&...> tie(Types&... t) noexcept;
7.返回值: tuple<Types&>(t...). 当t中一个参数是ignore时,对相应参数的赋值都无作用.
8.[Example: tie()将tuples解压到变量中. ignore可以使用在不需要的元素上.
int i; std::string s; tie(i, ignore, s) = make_tuple(42,3.14,"C++"); // i == 42, s == "C++"
-end note]
template <class... Tuples>
tuple<CTypes...> tuple_cat(Tuples&&... tpls);
9.在以下各段中, 让Ti为tuple中的第i个类型, 让Ui为remove_reference<Ti>::type, 并且tpi为函数参数包tpls中的第i个参数, 其中所有index均基于0.
10.11.12.13 略
20.4.2.5 Tuple helper classes
template <class... Types> class tuple_size<tuple<Types...> > : public integral_constant<size_t, sizeof...(Types)> { }; template <size_t I, class... Types> class tuple_element<I, tuple<Types...> > { public: typedef TI type; };
1.要求: I < sizeof...(Types). 如果I越界, 程序ill-formed.
2.类型: TI是Types的第I个元素的类型, index从0开始
template <class T> class tuple_size<const T>;
template <class T> class tuple_size<volatile T>;
template <class T> class tuple_size<const volatile T>;
3.让TS表示无cv类型T的tuple_size<T>. 然后三个模板中的每一个都应满足UnaryTypeTrait的要求, 其BaseCharacteristic是integral_constant<remove_cv<decltype(TS::value)>::type, TS::value>
template <size_t I, class T> class tuple_element<I, const T>;
template <size_t I, class T> class tuple_element<I, volatile T>;
template <size_t I, class T> class tuple_element<I, const volatile T>;
令TE表示无cv类型T的tuple_element<I, T>. 然后三个模板中的每一个都应满足TransformationTrait的要求, 成员typedef类型的名称如下:-第一个特化,add_const<TE::type>::type, -第二个特化,add_volatile<TE::type>::type, -第三个特化,add_cv<TE::type>::type
20.4.2.6 元素访问(Element access)
template <size_t I, class... Types>
typename tuple_element<I, tuple<Types...>>::type& get(tuple<Types...>& t) noexcept;
1.要求: I < sizeof...(Types).如果I越界, 程序ill-formed.
2.返回值: t的第I个元素的引用, index从0开始.
template <size_t I, class... types>
typename tuple_element<I, tuple<Types...>>::type&& get(tuple<Types...>&& t) noexcept;
3.作用: 等价于返回Equivalent to return std::forward<typename tuple_element<I, tuple<Types...>>::type&&>(get<I>(t));
4.Note: 如果Types中的T是某个引用类型X&, 则返回类型为X&, 而不是X&&. 但是, 如果元素类型为非引用类型T, 则返回类型为T&&.
template <size_t I, class... Types>
typename tuple_element<I, tuple<Types...>>::type const& get(const tuple<Types...>& t) noexcept;
5.要求: I < sizeof...(Types).如果I越界, 程序ill-formed.
6.返回值: t的第I个元素的const 引用, index从0开始.
7.[Note: Constness is shallow.如果Types中的T是某个引用类型X&,返回值是X&,而不是const X&. 但是, 如果元素类型是非引用类型T, 返回类型是const T&.这与将constness定义为引用类型的成员变量的方式一致. -end note]
8.[Note: get是一个非成员函数的理由是 如果实现了作为成员函数的这种设计, 依赖template参数的类型的代码需要使用template关键字. -end note]
20.4.2.7 相关运算符(Relational operators)
template<class... TTypes, class... UTypes>
bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
1.要求: 每个i, 其中0 <= i和i < sizeof...(Types), get<i>(t) == get<i>(u)是有效表达式, 返回可转换为bool的类型. sizeof...(TTypes) == sizeof...(UTypes).
2.返回值: 每个i, 如果get<i>(t) == get<i>(u), 返回true.对任意两个0长度的tuple e和f来说,e == f返回true.
3.作用: 从0开始按顺序执行基本比较.在第一个相等比较结果为false之后, 不执行任何比较或元素访问.
template<class... TTypes, class... UTypes>
bool operator<(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
4.要求: 每个i, 其中0 <= i和i < sizeof...(Types), get<i>(t) < get<i>(u)和get<i>(u) < get<i>(t)是有效表达式, 返回可转换为bool的类型. sizeof...(TTypes) == sizeof...(UTypes).
5.作用: t和u之前loxicographical比较的结果.结果定义如下:(bool)(get<0>(t) < get<0>(u)) || (!(bool)(get<0>(u) < get<0>(t)) && ttail < utail. 其中某个tuple r的rtail是一个包含除r的第一个元素以外的所有元素的tuple.对于任何两个零长度tuple e和f, e < f返回false.
剩下的和20.2.1/20.2.2要求一样
20.4.2.8 Tuple traits
template <class... Types, class Alloc>
struct uses_allocator<tuple<Types...>, Alloc> : true_type { };
要求: Alloc应该是个Allocator(17.6.3.5).
1.[Note: 此traits的特化informs其他库组件, 即使没有嵌套的allocator_type, 也可以使用alloctor构造tuple. -end note]
20.4.2.9 Tuple特化算法(Tuple specialized algorithms)
template <class... Types>
void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below);
1.备注: noexcept里的表达式等价于:
noexcept(x.swap(y))
2.作用: x.swap(y).
20.5 类模板 bitset
for align
头文件<bitset> 概要
#include <string> #include <iosfwd> // for istream, ostream namespace std { template <size_t N> class bitset; // 20.5.4 bitset operators: template <size_t N> bitset<N> operator&(const bitset<N>&, const bitset<N>&) noexcept; template <size_t N> bitset<N> operator|(const bitset<N>&, const bitset<N>&) noexcept; template <size_t N> bitset<N> operator^(const bitset<N>&, const bitset<N>&) noexcept; template <class charT, class traits, size_t N> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, bitset<N>& x); template <class charT, class traits, size_t N> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const bitset<N>& x); }
1.头文件<bitset>定义一个类模板和一些相关的函数, 用于表示和操作固定大小的位序列.
namespace std { template<size_t N> class bitset { public: // bit reference: class reference { friend class bitset; reference() noexcept; public: ~reference() noexcept; reference& operator=(bool x) noexcept; // for b[i] = x; reference& operator=(const reference&) noexcept; // for b[i] = b[j]; bool operator~() const noexcept; // flips the bit operator bool() const noexcept; // for x = b[i]; reference& flip() noexcept; // for b[i].flip(); }; // 20.5.1 constructors: constexpr bitset() noexcept; constexpr bitset(unsigned long long val) noexcept; template<class charT, class traits, class Allocator> explicit bitset(const basic_string<charT,traits,Allocator>& str, typename basic_string<charT,traits,Allocator>::size_type pos = 0, typename basic_string<charT,traits,Allocator>::size_type n = basic_string<charT,traits,Allocator>::npos, charT zero = charT(’0’), charT one = charT(’1’)); template <class charT> explicit bitset(const charT* str, typename basic_string<charT>::size_type n = basic_string<charT>::npos, charT zero = charT(’0’), charT one = charT(’1’)); // 20.5.2 bitset operations: bitset<N>& operator&=(const bitset<N>& rhs) noexcept; bitset<N>& operator|=(const bitset<N>& rhs) noexcept; bitset<N>& operator^=(const bitset<N>& rhs) noexcept; bitset<N>& operator<<=(size_t pos) noexcept; bitset<N>& operator>>=(size_t pos) noexcept; bitset<N>& set() noexcept; bitset<N>& set(size_t pos, bool val = true); bitset<N>& reset() noexcept; bitset<N>& reset(size_t pos); bitset<N> operator~() const noexcept; bitset<N>& flip() noexcept; bitset<N>& flip(size_t pos); // element access: constexpr bool operator[](size_t pos) const; // for b[i]; reference operator[](size_t pos); // for b[i]; unsigned long to_ulong() const; unsigned long long to_ullong() const; template <class charT = char, class traits = char_traits<charT>, class Allocator = allocator<charT>> basic_string<charT, traits, Allocator> to_string(charT zero = charT(’0’), charT one = charT(’1’)) const; size_t count() const noexcept; constexpr size_t size() noexcept; bool operator==(const bitset<N>& rhs) const noexcept; bool operator!=(const bitset<N>& rhs) const noexcept; bool test(size_t pos) const; bool all() const noexcept; bool any() const noexcept; bool none() const noexcept; bitset<N> operator<<(size_t pos) const noexcept; bitset<N> operator>>(size_t pos) const noexcept; }; // 20.5.3 hash support template <class T> struct hash; template <size_t N> struct hash<bitset<N>>; }
2.类模板bitset<N>描述了一个可以保存由固定位数N组成的序列.
3.每个bit表示值0(reset)或1(set).切换(toggle)一位是只将值0更改为1或者将值1更改为0. 每个bit有一个非负位置pos.一个bitset<N>对象和一些整型值互相转换时, bit位置pos对应bit value1<<pos. 对应于两个或多个bit的整数值是它们的bit值之和.
4.本节中描述的函数可以报告三种错误, 每种错误都与一个明显的异常相关:
无效参数错误与invalid_argument类型的异常相关
超出范围的错误与out_of_range类型的异常相关
溢出错误与overflow_error类型的异常相关
20.5.1 bitset构造函数
constexpr bitset() noexcept;
1.作用: 构造一个bitset<N>, 所有bit初始化为0.
constexpr bitset(unsigned long long val) noexcept;
2.作用: 构造一个bitset<N>, 初始化其首(最低) M bit位置为对应 val 的位值, 其中 M 是 unsigned long long 的位数和正在构造的 bitset 中的位数 N 的较小者. 如果 M 小于 N, 则剩余bit位置被初始化为零.
template <class charT, class traits, class Allocator>
explicit bitset(const basic_string<charT, traits, Allocator>& str,
typename basic_string<charT, traits, Allocator>::size_type pos = 0,
typename basic_string<charT, traits, Allocator>::size_type n = basic_string<charT, traits, Allocator>::npos,
charT zero = charT(’0’), charT one = charT(’1’));
3.要求: pos <= str.size().
4.Throws: 如果pos > str.size(),抛出 out_of_range.
5.作用: 确定初始化string的有效长度rlen, rlen=min(n,str.size() - pos).
如果在pos开头的任何其他字符都不为0或1, 则该函数将引发无效参数. 该函数使用traits::eq()比较字符值.
否则, 该函数将构造一个bitset<N>类的对象, 将第一个M bit位置初始化为由字符串str中相应字符确定的值. M是N和rlen中的较小者.
6.如果str中从位置pos开始的相应字符为0, 则构造的字符串的元素的值为零.否则, 元素的值为1. 字符位置pos + M-1对应于bit位置0.随后减少的字符位置对应于增加的bit位置.(?)
7.如果 M < N, 剩余的bit位被初始化为0.
template <class charT>
explicit bitset( const charT* str,
typename basic_string<charT>::size_type n = basic_string<charT>::npos,
charT zero = charT(’0’), charT one = charT(’1’));
8.作用: 构造一个bitset<N>对象就像bitset( n == basic_string<charT>::npos ? basic_string<charT>(str) : basic_string<charT>(str, n), 0, n, zero, one)
20.5.2 bitset members
bitset<N>& operator&=(const bitset<N>& rhs) noexcept;
1.作用: 清除*this中的每个bit, 为此清零rhs中对应的bit, 其他位保持不变.
2.返回值: *this.
bitset<N>& operator|=(const bitset<N>& rhs) noexcept;
3.作用: set*this中的每个bit, 为此set rhs中对应的bit, 其他位保持不变.
4.返回值: *this.
bitset<N>& operator^=(const bitset<N>& rhs) noexcept;
5.作用: 切换*this中的每个bit, 为此切换rhs中对应的bit, 其他位保持不变.
6.返回值: *this.
bitset<N>& operator<<=(size_t pos) noexcept;
7.作用: 用一个确定的值按如下方式替换在*this中I位置的每个bit:
如果 I < pos,新值是0;
如果 I >= pos,新值是 I - pos 处先前的值.
8.返回值: *this.
bitset<N>& operator>>=(size_t pos) noexcept;
9.作用: 用一个确定的值按如下方式替换在*this中I位置的每个bit:
如果 pos >= N - I,新值是0;
如果 pos < N - I,新值是 I + pos 处先前的值.
10.返回值: *this.
bitset<N>& set() noexcept;
11.作用: 设置*this的所有bit.
12.返回值: *this.
bitset<N>& set(size_t pos, bool val = true);
13.要求: pos是合理的.
14.Throws: 如果pos不对应一个合理的bit位置, 抛出out_of_range.
15.作用: 在*this中位置pos的bit中保存一个新值.如果val为非零, 则保存的值为1, 否则为0.
16.返回值: *this.
bitset<N>& reset() noexcept;
17.作用: 重置*this的所有bit.
18.返回值: *this.
bitset<N>& reset(size_t pos);
19.要求: pos是合理的.
20.Throws: 如果pos不对应一个合理的bit位置, 抛出out_of_range.
21.作用: 重置*this中在pos位置的bit.
22.返回值: *this.
bitset<N> operator~() const noexcept;
23.作用: 构造一个bitset<N>对象x并且用*this初始化.
24.返回值: x.flip().
bitset<N>& flip() noexcept;
25.作用: 切换*this中所有bit.
26.返回值: *this.
bitset<N>& flip(size_t pos);
27.要求: pos是合理的.
28.Throws: 如果pos不对应一个合理的bit位置, 抛出out_of_range.
29.作用: 切换*this中在pos位置的bit.
30.返回值: *this.
unsigned long to_ulong() const;
31.Throws: 如果*this中的值不能被unsigned long表示, 抛出overflow_error.
32.返回值: x.
unsigned long long to_ullong() const;
33.Throws: 如果*this中的值不能被unsigned long long表示, 抛出overflow_error.
34.返回值: x.
template <class charT = char, class traits = char_traits<charT>, class Allocator = allocator<charT>>
basic_string<charT, traits, Allocator> to_string(charT zero = charT(’0’), charT one = charT(’1’)) const;
35.作用: 构造一个合适的string对象并且用长度N的的字符初始化.每个字符通过*this中对应的bit位的值确定. 字符位置N-1对应bit位置0.随后减少的字符位置对应于增加的bit位置.bit值0变成字符zero,bit值1变成字符one.
36.返回值: 创建的对象.
size_t count() const noexcept;
37.返回值: *this中bit集合的位置的统计数.
constexpr size_t size() noexcept;
38.返回值: N.
bool operator==(const bitset<N>& rhs) const noexcept;
39.返回值: 如果*this中每bit的值等于rhs中对应bit的值, true.
bool operator!=(const bitset<N>& rhs) const noexcept;
40.返回值: 如果!(*this == rhs) , true.
bool test(size_t pos) const;
41.要求: pos是合理的.
42.Throws: 如果pos不对应一个合理的bit位置, 抛出out_of_range.
43.返回值: 如果*this中pos位置的bit是值1, true.
bool all() const noexcept;
44.返回值: count() == size().
bool any() const noexcept;
45.返回值: count() != 0.
bool none() const noexcept;
46.返回值: count() == 0.
bitset<N> operator<<(size_t pos) const noexcept;
47.返回值: bitset<N>(*this) <<= pos.
bitset<N> operator>>(size_t pos) const noexcept;
48.返回值: bitset<N>(*this) >>= pos.
constexpr bool operator[](size_t pos);
49.要求: pos是合理的.
50.返回值: 如果*this中pos位置的bit是值1, true;否则false.
51.Throws: Nothing.
bitset<N>::reference operator[](size_t pos);
52.要求: pos是合理的.
53.返回值: 一个bitset<N>::reference对象, (this)[pos] == this->test(pos) && (this)[pos] = val 等于 this->set(pos, val).
54.Throws: Nothing.
55.备注: 为了确定是否存在数据竞争, 通过结果引用进行的任何访问或更新都可能分别访问或修改整个基础bitset.
20.5.3 bitset hash support
template <size_t N> struct hash<bitset<N>>;
1.要求: 模板特化需满足类模板hash(20.8.12)的要求.
20.5.4 bitset 运算符
bitset<N> operator&(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
1.返回值: bitset<N>(lhs) &= rhs.
bitset<N> operator|(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
2.返回值: bitset<N>(lhs) |= rhs.
bitset<N> operator^(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
3.返回值: bitset<N>(lhs) ^= rhs.
template <class charT, class traits, size_t N>
basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, bitset<N>& x);
4.一个格式化输入函数.
5.作用: 从is中提取最多N个字符.将这些字符保存在一个basic_string<charT, traits>临时对象str中, 然后计算表达式x = bitset<N>(str).N个字符被提取并保存直到发生以下任一情况:
- N个字符被提取并保存.
- 输入队列读取到eof.
- 下一个输入字符既不是is.widen('0')也不是is.widen('1')(在这种情况下, 不会提取字符).
6.如果没有字符保存在str,调用is.setstate(ios_base::failbit)(这可能会抛出ios_base::failure(27.5.5.4)).
7.返回值: is.
template <class charT, class traits, size_t N>
basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const bitset<N>& x);
8.返回值: os << x.template to_string<charT,traits,allocator<charT>>(use_facet<ctype<charT>>(os.getloc()).widen(’0’),use_facet<ctype<charT>>(os.getloc()).widen(’1’))
20.6 Memory
for align
20.6.1 概览
1.本条款描述了头文件<memory>中的内容和一些C头文件<cstdlib>,<cstring>的内容.
20.6.2 头文件<memory> 概要
1.头文件<memory>定义了几种类型和模板函数, 这些函数描述指针和类似指针的类型的属性, 管理容器和其他模板类型的内存管理, 并在单元化的内存缓冲区中构造多个对象. 头文件定义模板unique_ptr, shared_ptr, weak_ptr和对这些类型的对象进行操作的各种模板函数(20.7).
namespace std { // 20.6.3, pointer traits template <class Ptr> struct pointer_traits; template <class T> struct pointer_traits<T*>; // 20.6.4, pointer safety enum class pointer_safety { relaxed, preferred, strict }; void declare_reachable(void *p); template <class T> T *undeclare_reachable(T *p); void declare_no_pointers(char *p, size_t n); void undeclare_no_pointers(char *p, size_t n); pointer_safety get_pointer_safety() noexcept; // 20.6.5, pointer alignment function void *align(std::size_t alignment, std::size_t size, void *&ptr, std::size_t& space); // 20.6.6, allocator argument tag struct allocator_arg_t { }; constexpr allocator_arg_t allocator_arg = allocator_arg_t(); // 20.6.7, uses_allocator template <class T, class Alloc> struct uses_allocator; // 20.6.8, allocator traits template <class Alloc> struct allocator_traits; // 20.6.9, the default allocator: template <class T> class allocator; template <> class allocator<void>; template <class T, class U> bool operator==(const allocator<T>&, const allocator<U>&) noexcept; template <class T, class U> bool operator!=(const allocator<T>&, const allocator<U>&) noexcept; // 20.6.10, raw storage iterator: template <class OutputIterator, class T> class raw_storage_iterator; // 20.6.11, temporary buffers: template <class T> pair<T*,ptrdiff_t> get_temporary_buffer(ptrdiff_t n) noexcept; template <class T> void return_temporary_buffer(T* p); // 20.6.12, specialized algorithms: template <class T> T* addressof(T& r) noexcept; template <class InputIterator, class ForwardIterator> ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result); template <class InputIterator, class Size, class ForwardIterator> ForwardIterator uninitialized_copy_n(InputIterator first, Size n, ForwardIterator result); template <class ForwardIterator, class T> void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& x); template <class ForwardIterator, class Size, class T> ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T& x); // 20.7.1 class template unique_ptr: template <class T> class default_delete; template <class T> class default_delete<T[]>; template <class T, class D = default_delete<T>> class unique_ptr; template <class T, class D> class unique_ptr<T[], D>; template <class T1, class D1, class T2, class D2> bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T1, class D1, class T2, class D2> bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T1, class D1, class T2, class D2> bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T1, class D1, class T2, class D2> bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T1, class D1, class T2, class D2> bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T1, class D1, class T2, class D2> bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T, class D> bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept; template <class T, class D> bool operator==(nullptr_t, const unique_ptr<T, D>& y) noexcept; template <class T, class D> bool operator!=(const unique_ptr<T, D>& x, nullptr_t) noexcept; template <class T, class D> bool operator!=(nullptr_t, const unique_ptr<T, D>& y) noexcept; template <class T, class D> bool operator<(const unique_ptr<T, D>& x, nullptr_t); template <class T, class D> bool operator<(nullptr_t, const unique_ptr<T, D>& y); template <class T, class D> bool operator<=(const unique_ptr<T, D>& x, nullptr_t); template <class T, class D> bool operator<=(nullptr_t, const unique_ptr<T, D>& y); template <class T, class D> bool operator>(const unique_ptr<T, D>& x, nullptr_t); template <class T, class D> bool operator>(nullptr_t, const unique_ptr<T, D>& y); template <class T, class D> bool operator>=(const unique_ptr<T, D>& x, nullptr_t); template <class T, class D> bool operator>=(nullptr_t, const unique_ptr<T, D>& y); // 20.7.2.1, class bad_weak_ptr: class bad_weak_ptr; // 20.7.2.2, class template shared_ptr: template<class T> class shared_ptr; // 20.7.2.2.7, shared_ptr comparisons: template<class T, class U> bool operator==(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept; template<class T, class U> bool operator!=(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept; template<class T, class U> bool operator<(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept; template<class T, class U> bool operator>(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept; template<class T, class U> bool operator<=(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept; template<class T, class U> bool operator>=(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept; template <class T> bool operator==(const shared_ptr<T>& x, nullptr_t) noexcept; template <class T> bool operator==(nullptr_t, const shared_ptr<T>& y) noexcept; template <class T> bool operator!=(const shared_ptr<T>& x, nullptr_t) noexcept; template <class T> bool operator!=(nullptr_t, const shared_ptr<T>& y) noexcept; template <class T> bool operator<(const shared_ptr<T>& x, nullptr_t) noexcept; template <class T> bool operator<(nullptr_t, const shared_ptr<T>& y) noexcept; template <class T> bool operator<=(const shared_ptr<T>& x, nullptr_t) noexcept; template <class T> bool operator<=(nullptr_t, const shared_ptr<T>& y) noexcept; template <class T> bool operator>(const shared_ptr<T>& x, nullptr_t) noexcept; template <class T> bool operator>(nullptr_t, const shared_ptr<T>& y) noexcept; template <class T> bool operator>=(const shared_ptr<T>& x, nullptr_t) noexcept; template <class T> bool operator>=(nullptr_t, const shared_ptr<T>& y) noexcept; // 20.7.2.2.8, shared_ptr specialized algorithms: template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept; // 20.7.2.2.9, shared_ptr casts: template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const& r) noexcept; template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const& r) noexcept; template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const& r) noexcept; // 20.7.2.2.10, shared_ptr get_deleter: template<class D, class T> D* get_deleter(shared_ptr<T> const& p) noexcept; // 20.7.2.2.11, shared_ptr I/O: template<class E, class T, class Y> basic_ostream<E, T>& operator<< (basic_ostream<E, T>& os, shared_ptr<Y> const& p); // 20.7.2.3, class template weak_ptr: template<class T> class weak_ptr; // 20.7.2.3.6, weak_ptr specialized algorithms: template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept; // 20.7.2.3.7, class template owner_less: template<class T> class owner_less; // 20.7.2.4, class template enable_shared_from_this: template<class T> class enable_shared_from_this; // 20.7.2.5, shared_ptr atomic access: template<class T> bool atomic_is_lock_free(const shared_ptr<T>* p); template<class T> shared_ptr<T> atomic_load(const shared_ptr<T>* p); template<class T> shared_ptr<T> atomic_load_explicit(const shared_ptr<T>* p, memory_order mo); template<class T> void atomic_store(shared_ptr<T>* p, shared_ptr<T> r); template<class T> void atomic_store_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo); template<class T> shared_ptr<T> atomic_exchange(shared_ptr<T>* p, shared_ptr<T> r); template<class T> shared_ptr<T> atomic_exchange_explicit(shared_ptr<T>* p, shared_ptr<T> r, template<class T> bool atomic_compare_exchange_weak( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w); template<class T> bool atomic_compare_exchange_strong( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w); template<class T> bool atomic_compare_exchange_weak_explicit( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w, memory_order success, memory_order failure); template<class T> bool atomic_compare_exchange_strong_explicit( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w, memory_order success, memory_order failure); // 20.7.2.6 hash support template <class T> struct hash; template <class T, class D> struct hash<unique_ptr<T, D>>; template <class T> struct hash<shared_ptr<T>>; // D.10, auto_ptr (deprecated) template <class X> class auto_ptr; }
20.6.3 Pointer traits
1.类模板pointer_traits为类似指针的类型的某些属性提供了统一的接口.
namespace std { template <class Ptr> struct pointer_traits { typedef Ptr pointer; typedef see below element_type; typedef see below difference_type; template <class U> using rebind = see below; static pointer pointer_to(see below r); }; template <class T> struct pointer_traits<T*> { typedef T* pointer; typedef T element_type; typedef ptrdiff_t difference_type; template <class U> using rebind = U*; static pointer pointer_to(see below r) noexcept; }; }
20.6.3.1 Pointer traits member types
typedef see below element_type;
1.类型: 若存在则为 Ptr::element_type.否则若 Ptr 是模板实例化 Template<T, Args...>则为T. ( Ptr::element_type if such a type exists; otherwise, T if Ptr is a class template instantiation of the form SomePointer<T, Args>, where Args is zero or more type arguments; otherwise, the specialization is ill-formed.)
typedef see below difference_type;
2.类型: 若存在则为 Ptr::difference_type , 否则为 std::ptrdiff_t.
template <class U> using rebind = see below;
3.别名模板: 若存在则为 Ptr::rebind<U> ,否则若 Ptr 是模板实例化Template<T, Args...> 则为Template<U, Args...>.
20.6.3.2 Pointer traits member functions
static pointer pointer_traits::pointer_to(see below r);
static pointer pointer_traits<T*>::pointer_to(see below r) noexcept;
1.备注: 如果element_type(可能cv限定)是void,r是未指定的;否则,r是T&.
2.返回值: 第一个模板函数返回通过调用Ptr::pointer_to(r)获得的指向r的可解引用的指针;如果Ptr没有一个匹配的静态成员函数pointer_to,这个函数的实例ill-formed. 第二个模板函数返回std::addressof(r).
20.6.4 Pointer safety
1.一个完整的对象被声明为reachable,当带有一个引用了该对象的参数对declare_reachable的调用次数超过了带有一个引用了该对象的参数对undeclare_reachable的调用次数.
(当declare_reachable(p)的次数 > undeclare_reachable(p)的次数,p是reachable.)
(A complete object is declared reachable while the number of calls to declare_reachable with an argument referencing the object exceeds the number of calls to undeclare_reachable with an argument referencing the object.)
void declare_reachable(void *p);
2.要求: p应该是安全派生的指针或null值.
3.作用: 如果p非null,被p引用的完整对象随后被声明为reachable.
4.Throws: 如果系统无法分配跟踪声明为reachable的对象可能需要的其他内存,则可能抛出std::bad_alloc.
template <class T> T *undeclare_reachable(T *p);
5.要求: 如果p非null,被p引用的完整对象应事先被声明为reachable,并且从调用时间到该对象的最后undeclare_reachable(p)调用应处于活跃状态.
6.返回值: 一个p的安全派生的拷贝,它应等于p.
7.Throws: Nothing.
8.[Note: 除非遇到匹配的calltoundeclare_reachable(p),否则对declare_reachable(p)的调用会消耗少量的内存,除非引用对象占用了该内存.长时间运行的程序应安排调用匹配. -end note]
void declare_no_pointers(char *p, size_t n);
9.要求: 当前没有在指定的范围内的任何字节注册到clarate_no_pointers(). 如果指定范围在分配的对象中,则它必须完全在单个分配的对象之内. 该对象必须处于活动状态,直到相应的undeclare_no_pointers()调用为止. [Note: 在垃圾回收实现中,对象中的区域已通过clarify_no_pointers()注册的事实不应阻止对象的收集. -end note]
10.从p开始的n个字节不再包含可跟踪的指针位置,而与它们的类型无关。因此,如果指针所指向的对象是由全局运算符new创建的,并且以前未声明可访问的,则不能取消指向该指针的引用。[Note: 这可以用于通知垃圾收集器或泄漏检测器不需要跟踪此内存区域. -end note]
11.Throws: Nothing.
12.[Note: 在某些情况下,实现可能需要分配内存.但是,如果内存分配失败,则可以忽略该请求. -end note]
void undeclare_no_pointers(char *p, size_t n);
13.要求: 必须事先将相同的范围传递给declare_no_pointers().
14.解除注册先前以std::declare_no_pointers()注册的范围.必须在对象的生存期结束之前调用它.
15.Throws: Nothing.
pointer_safety get_pointer_safety() noexcept;
16.返回值: 如果实现具有严格的指针安全性,返回pointer_safety::strict. 如果实现具有宽松的指针安全性,由实现定义是否返回pointer_safety::relaxed 或 pointer_safety::preferred
20.6.5 Align
void *align(std::size_t alignment, std::size_t size, void *&ptr, std::size_t& space);
1.作用: 如果可以通过对齐带有长度space的ptr指向的buffer来对齐存储的size字节, 该函数将ptr更新为指向此类存储的第一个可能的地址,并通过对齐所使用的字节数减少space.否则,该函数不做任何事.
2.要求:
- 对齐方式应为基本对齐方式值或此实现中支持的扩展对齐方���值.
- ptr应指向至少space字节的连续存储.
3.返回值: 如果申请的对齐的buffer无法匹配可用空间,返回null.否则返回ptr的调整值.
4.[Note: 该函数更新ptr和space参数,使可以对同一buffer使用不同的alignment和size参数重复调用. -end note]
20.6.6 Allocator argument tag
namespace std { struct allocator_arg_t { }; constexpr allocator_arg_t allocator_arg = allocator_arg_t(); }
1.allocator_arg_t 是用于消除构造函数和函数重载歧义的空结构体类型. 特别的,一些类型拥有allocator_arg_t作为第一参数的构造函数,紧接着是满足Allocator类型要求的参数.
20.6.7 uses_allocator
20.6.7.1 uses_allocator trait
template <class T, class Alloc> struct uses_allocator;
1.备注: 自动检测T是否有可从Alloc转换的嵌套类型allocator_type.符合BinaryTypeTrait要求. 如果一个类型T::allocator_type存在并且is_convertible<Alloc,T::allocator_type>::value != false, 实现需提供从true_type派生的定义; 否则,它应该从false_type派生. 一个程序可以特化此模板来从true_type派生出用户定义的类型T,该类型T么有嵌套的allocator_type,但是仍可以使用分配器构造,必须满足下列要求之一:
- 构造函数的第一个参数的类型为allocator_arg_t, 第二个参数的类型为Alloc.
- 构造函数的最后一个参数的类型为Alloc.
20.6.7.2 uses-allocator construction
1.带有分配器Alloc进行uses-allocator construction是指分别使用类型V1,V2,...,VN的构造函数参数v1,v2,...,vN和类型为的分配器alloc构造类型T的对象obj的构造. 有以下规则:
- 如果uses_allocator<T,Alloc>::valueisfalseandis_constructible<T,V1,V2,...,VN>::value为true,则obj初始化为obj(v1,v2,...,vN);
- 否则,如果uses_allocator<T,Alloc>::value为true并且is_constructible<T,allocator_arg_t,Alloc,V1,V2,...,VN>::value为true,则obj初始化为obj(allocator_arg,alloc,v1, v2,...,vN);
- 否则,如果uses_allocator<T,Alloc>::value为true并且is_constructible<T,V1,V2,...,VN,Alloc>::value为true,则obj初始化为obj(v1,v2,..., vN,alloc);
- 否则,uses-allocator construction的请求ill-formed.[Note: 如果uses_allocator<T,Alloc>::value为true,但特定的构造函数不使用分配器,将导致错误。此定义可防止将分配器传递给元素的无提示失败。-end note]
20.6.8 Allocator traits
1.类模板allocator_traits提供所有alloc类型的统一接口.一个allocator不能是一个非类类型,但是,即使allocator_traits提供了所需的整个接口. [Note: 因此,创建一个派生自allocator的类总是可能的. -end note]
namespace std { template <class Alloc> struct allocator_traits { typedef Alloc allocator_type; typedef typename Alloc::value_type value_type; typedef see below pointer; typedef see below const_pointer; typedef see below void_pointer; typedef see below const_void_pointer; typedef see below difference_type; typedef see below size_type; typedef see below propagate_on_container_copy_assignment; typedef see below propagate_on_container_move_assignment; typedef see below propagate_on_container_swap; template <class T> using rebind_alloc = see below; template <class T> using rebind_traits = allocator_traits<rebind_alloc<T>>; static pointer allocate(Alloc& a, size_type n); static pointer allocate(Alloc& a, size_type n, const_void_pointer hint); static void deallocate(Alloc& a, pointer p, size_type n); template <class T, class... Args> static void construct(Alloc& a, T* p, Args&&... args); template <class T> static void destroy(Alloc& a, T* p); static size_type max_size(const Alloc& a); static Alloc select_on_container_copy_construction(const Alloc& rhs); }; }
typedef see below pointer;
1.Type: 如果这样的类型存在,Alloc::pointer;否则,value_tyope* .
typedef see below const_pointer;
2.Type: 如果这样的类型存在,Alloc::const_pointer;否则,pointer_traits<pointer>::rebind<const value_type>.
typedef see below void_pointer;
3.Type: 如果这样的类型存在,Alloc::void_pointer;否则,pointer_traits<pointer>::rebind<void>.
typedef see below const_void_pointer;
4.Type: 如果这样的类型存在,Alloc::const_void_pointer;否则,pointer_traits<pointer>::rebind<const void>.
typedef see below difference_type;
5.Type: 如果这样的类型存在,Alloca::difference_type;否则,pointer_traits<pointer>::difference_type.
typedef see below size_type;
6.Type: 如果这样的类型存在,Alloca::size_type;否则,make_unsigned<difference_type>::type.
typedef see below propagate_on_container_copy_assignment;
7.Type: 如果这样的类型存在,Alloc::propagate_on_container_copy_assignment;否则,false_type.
typedef see below propagate_on_container_move_assignment;
8.Type: 如果这样的类型存在,Alloc::propagate_on_container_move_assignment;否则,false_type.
typedef see below propagate_on_container_swap;
9.Type: 如果这样的类型存在, Alloc::propagate_on_container_swap;否则,false_type.
template <class T> using rebind_alloc = see below;
10.别名模板: 如果这样的类型存在, Alloc::rebind<T>::other; 否则,如果Alloc是Alloc<U,Args>的类模板实例化,Alloc<T,Args>,其中Args是0个或多个类型参数;否则rebind_alloc ill-formed.
20.6.8.2 Allocator traits static member functions
static pointer allocate(Alloc& a, size_type n);
1.返回值: a.allocate(n).
static pointer allocate(Alloc& a, size_type n, const_void_pointer hint);
2.返回值: a.allocate(n,hint)(如果表达式是良好的.);否则,a.allocate(n).
static void deallocate(Alloc& a, pointer p, size_type n);
3.作用: 调用a.deallocate(p,n).
4.Throws: Nothing.
template <class T, class... Args> static void construct(Alloc& a, T* p, Args&&... args);
5.作用: 如果调用是良好的,调用a.construct(p,std::forward<Args>(args)...); 否则,执行::new(static_cast<void*>(p)) T(std::forward<Args>(args)...).
template <class T> static void destroy(Alloc& a, T* p);
6.作用: 如果调用是良好的,调用a.destroy(p);否则,执行p->~T().
static size_type max_size(Alloc& a);
7.返回值: 如果表达式是良好的,a.max_size();否则,numeric_limits<size_type>::max().
static Alloc select_on_container_copy_construction(const Alloc& rhs);
8.返回值: 如果表达式是良好的,rhs.select_on_container_copy_construction();否则,rhs.
20.6.9 The default allocator
namespace std { template <class T> class allocator; // specialize for void: template <> class allocator<void> { public: typedef void* pointer; typedef const void* const_pointer; // reference-to-void members are impossible. typedef void value_type; template <class U> struct rebind { typedef allocator<U> other; }; }; template <class T> class allocator { public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; typedef T value_type; template <class U> struct rebind { typedef allocator<U> other; }; allocator() noexcept; allocator(const allocator&) noexcept; template <class U> allocator(const allocator<U>&) noexcept; ~allocator(); pointer address(reference x) const noexcept; const_pointer address(const_reference x) const noexcept; pointer allocate(size_type, allocator<void>::const_pointer hint = 0); void deallocate(pointer p, size_type n); size_type max_size() const noexcept; template<class U, class... Args> void construct(U* p, Args&&... args); template <class U> void destroy(U* p); }; }
20.6.9.1 allocator members
1.除析构函数外,default allocator的成员函数不得由于不同线程并发调用这些成员函数而导致数据竞争. 对这些allocate或deallocate特定存储单元的功能的调用应以单个总顺序发生,并且每个此类deallocation操作应在该顺序的下一次allocation(如果有)之前发生。
pointer address(reference x) const noexcept;
2.返回值: x引用的对象的真实地址,即使存在重载的operator&.
const_pointer address(const_reference x) const noexcept;
3.返回值: x引用的对象的真实地址,即使存在重载的operator&.
pointer allocate(size_type n, allocator<void>::const_pointer hint = 0);
4.[Note: 在容器成员函数中,相邻元素的地址通常是传递给hint参数的. -end note]
5.返回值: 指向 一个n*sizeof(T) 大小的数组的最初的元素,类型T的对象是适当对齐的. 由实现定义是否支持over-aligned类型.
6.备注: 存储是通过::operator new(std::size_t)获得的,但未指定何时和如何调用此函数. hint的使用是未指定的,但如果实现需要的话,旨在帮助局部性.
7.Throws: 如果不能获得存储(storage),bad_alloc.
void deallocate(pointer p, size_type n);
8.要求: p应该是从allocate()中获得的指针值. n等于作为第一个参数传递给调用p的allocate的值.
9.作用: deallocate被p引用的内存空间.
10.备注: 使用 ::operator delete(void*), 但未指定何时调用.
size_type max_size() const noexcept;
11.返回值: 调用allocate(N,0)可能成功的最大值N.
template <class U, class... Args> void construct(U* p, Args&&... args);
12.作用: ::new((void*)p) U(std::forward<Args>(args)...)
template <class U> void destroy(U* p);
13.作用: p->~U().
20.6.9.2 allocator globals
template <class T1, class T2> bool operator==(const allocator<T1>&, const allocator<T2>&) noexcept;
1.返回值: true.
template <class T1, class T2> bool operator!=(const allocator<T1>&, const allocator<T2>&) noexcept;
2.返回值: false.
20.6.10 Raw storage iterator
1.提供raw_storage_iterator使算法将其结果保存到未初始化的内存中. 形式模板参数OutputIterator要求其operator*返回为其定义的operator&的对象并返回指向T的指针,并且还需要满足输出迭代器的要求.
namespace std { template <class OutputIterator, class T> class raw_storage_iterator : public iterator<output_iterator_tag,void,void,void,void> { public: explicit raw_storage_iterator(OutputIterator x); raw_storage_iterator<OutputIterator,T>& operator*(); raw_storage_iterator<OutputIterator,T>& operator=(const T& element); raw_storage_iterator<OutputIterator,T>& operator++(); raw_storage_iterator<OutputIterator,T> operator++(int); }; }
explicit raw_storage_iterator(OutputIterator x);
2.作用: 初始化迭代器来指向x指向的相同值.
raw_storage_iterator<OutputIterator,T>& operator*();
3.返回值: *this.
raw_storage_iterator<OutputIterator,T>& operator=(const T& element);
4.作用: 在迭代器指向的地方从element构造一个值.
5.返回值: iterator的引用.
raw_storage_iterator<OutputIterator,T>& operator++();
6.作用: 前++:advance迭代器并返回对更新后的迭代器的引用.
raw_storage_iterator<OutputIterator,T> operator++(int);
7.作用: 后++:advance迭代器并返回对更新前的迭代器的引用.
20.6.11 Temporary buffers
template <class T> pair<T*, ptrdiff_t> get_temporary_buffer(ptrdiff_t n) noexcept;
1.作用: 获得足以保存n个相邻T对象的存储空间的指针.由实现定义是否支持过度对齐(over-aligned)的类型.
2.返回值: 一个包含buffer地址和容量(以sizeof(T)为单位)的pair, 或如果无法获得存储空间 || n<=0,一个0值pair.
template <class T> void return_temporary_buffer(T* p);
3.作用: deallocate p指向的buffer.
4.要求: buffer需是事先通过get_temporary_buffer分配的.
20.6.12 Specialized algorithms
1.在以下算法中,用作正式模板参数的所有迭代器都需要让其operator*返回其定义了operator&的对象并返回指向T的指针. 在uninitialized_copy算法中,需要正式的模板参数InputIterator才能满足输入迭代器的要求. 在以下所有所有算法中,形式模板参数ForwardIterator必须满足正向迭代器的要求,并且必须具有以下特性:不会因有效迭代器的递增,赋值,比较或解引用抛出异常. 在以下算法中,如果引发异常,则没有效果.
20.6.12.1 addressof
template <class T> T* addressof(T& r) noexcept;
1.返回值: r引用的对象或函数的实际地址,即重载了operator&.
20.6.12.2 uninitialized_copy
template <class InputIterator, class ForwardIterator>
ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result);
1.作用:
for (; first != last; ++result, ++first) ::new (static_cast<void*>(&*result)) typename iterator_traits<ForwardIterator>::value_type(*first);
2.返回值: result.
template <class InputIterator, class Size, class ForwardIterator>
ForwardIterator uninitialized_copy_n(InputIterator first, Size n, ForwardIterator result);
3.作用:
for ( ; n > 0; ++result, ++first, --n) { ::new (static_cast<void*>(&*result)) typename iterator_traits<ForwardIterator>::value_type(*first); }
4.返回值: result.
20.6.12.3 uninitialized_fill
template <class ForwardIterator, class T>
void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& x);
1.作用:
for (; first != last; ++first) ::new (static_cast<void*>(&*first)) typename iterator_traits<ForwardIterator>::value_type(x);
20.6.12.4 uninitialized_fill_n
template <class ForwardIterator, class Size, class T>
ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T& x);
1.作用:
for (; n--; ++first) ::new (static_cast<void*>(&*first)) typename iterator_traits<ForwardIterator>::value_type(x); return first;
20.6.13 C library
1.Table 45.
2.内容与标准C库头文件<stdlib.h>相同,但有以下更改.
3.函数scalloc(),malloc()和realloc()不会尝试通过调用::operator new()来分配存储空间.
4.函数free()不会通过调用::operator delete()来尝试deallocate存储空间.
5.allocation时,直接由malloc(),calloc()或realloc()申请的存储空间隐式声明为reachable; deallocation时,结束其reachable,并且不需要因为undeclare_reachable()的调用而结束reachable. [Note: 这使得现有的C库不受安全派生的指针的限制作用,但代价是为malloc()分配的对象提供少得多的垃圾回收和泄漏检测选项.它还允许malloc()通过单独的分配空间来实现,从而绕过常规的clarify_reachable()实现. 绝对不要将上述函数用作clarify_reachable()的替代方法,并且强烈建议新编写的代码将使用这些函数分配的内存视为使用了new运算符分配的内存. -end note]
6.Table 46.
7.内容和标准C库头文件<string.h>相同,对memchr()的更改在21.7中指定.
20.7 智能指针(Smart pointers)
for align
20.7.1 类模板 unique_ptr
1.unique pointer通过s指针拥有并管理另一对象.更确切地说,unique pointer是对象u,它保存指向第二个对象p的指针, 并且在u自身被销毁时(离开块作用域时)将释放p.在上下文中,u拥有p.
2.u释放p的机制称为p关联的deleter,该函数对象的正确调用会导致p适当的释放(通常是delete).
3.u.p表示u存储的指针,让u.d表示关联的deleter.根据要求,可以使用另一个指针和deleter reset(replace)u.p和u.d, 但必须在replace完成之前通过关联的deleter正确释放其拥有的对象.
4.另外, 可以根据请求将所有权转移到另一个unique pointer u2. 转移完成后, 保持下列后条件:
- u2.p等于转移前的u.p
- u.p等于nullptr
- 如果转移前的u.d保持某种状态, 此状态已转移给u2.d
与reset一样, u2必须通过转移前关联的deleter正确释放准备转移的对象, 然后才能认为所有权转移完成.
[Note: deleter的状态从不被copy, 仅当所有权转移时move和swap. -end note]
5.从本小节中指定的unique_ptr模板实例化的每个类型为U的对象都具有上述唯一指针的严格所有权语义. 为了部分满足这些语义,每个这样的U是MoveConstructible和MoveAssignable, 但不是CopyConstructible或CopyAssignable. unique_ptr的模板参数T可能是不完整的类型.
6.[Note: unique_ptr的使用包括为动态分配的内存提供异常安全, 将动态分配的内存的所有权转移给函数以及从函数返回动态分配的内存. -end note]
namespace std { template<class T> struct default_delete; template<class T> struct default_delete<T[]>; template<class T, class D = default_delete<T>> class unique_ptr; template<class T, class D> class unique_ptr<T[], D>; template<class T, class D> void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept; template<class T1, class D1, class T2, class D2> bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template<class T1, class D1, class T2, class D2> bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template<class T1, class D1, class T2, class D2> bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template<class T1, class D1, class T2, class D2> bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template<class T1, class D1, class T2, class D2> bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template<class T1, class D1, class T2, class D2> bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T, class D> bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept; template <class T, class D> bool operator==(nullptr_t, const unique_ptr<T, D>& y) noexcept; template <class T, class D> bool operator!=(const unique_ptr<T, D>& x, nullptr_t) noexcept; template <class T, class D> bool operator!=(nullptr_t, const unique_ptr<T, D>& y) noexcept; template <class T, class D> bool operator<(const unique_ptr<T, D>& x, nullptr_t); template <class T, class D> bool operator<(nullptr_t, const unique_ptr<T, D>& y); template <class T, class D> bool operator<=(const unique_ptr<T, D>& x, nullptr_t); template <class T, class D> bool operator<=(nullptr_t, const unique_ptr<T, D>& y); template <class T, class D> bool operator>(const unique_ptr<T, D>& x, nullptr_t); template <class T, class D> bool operator>(nullptr_t, const unique_ptr<T, D>& y); template <class T, class D> bool operator>=(const unique_ptr<T, D>& x, nullptr_t); template <class T, class D> bool operator>=(nullptr_t, const unique_ptr<T, D>& y); }
20.7.1.1 Default deleters
20.7.1.1.1 In general
1.类模板default_delete作为默认deleter为类模板unique_ptr服务.
2.default_deleted的模板参数T可能是未完成类型.
20.7.1.1.2 default_delete
namespace std { template <class T> struct default_delete { constexpr default_delete() noexcept = default; template <class U> default_delete(const default_delete<U>&) noexcept; void operator()(T*) const; }; }
template <class U> default_delete(const default_delete<U>& other) noexcept;
1.作用: 从另一个default_delete<U>对象构造一个default_delete对象.
2.备注: 这个构造函数不参与重载决议, 除非U*可隐式转换为T*.
void operator()(T *ptr) const;
3.作用: 对ptr调用delete.
4.备注: 如果T是一个未完成类型, 程序ill-formed.
20.7.1.1.3 default_delete<T[]>
namespace std { template <class T> struct default_delete<T[]> { constexpr default_delete() noexcept = default; void operator()(T*) const; template <class U> void operator()(U*) const = delete; }; }
void operator()(T* ptr) const;
1.作用: 对ptr调用delete[].
2.备注: 如果T是一个未完成类型, 程序ill-formed.
20.7.1.2 unique_ptr for single objects
namespace std { template <class T, class D = default_delete<T>> class unique_ptr { public: typedef see below pointer; typedef T element_type; typedef D deleter_type; // 20.7.1.2.1, constructors constexpr unique_ptr() noexcept; explicit unique_ptr(pointer p) noexcept; unique_ptr(pointer p, see below d1) noexcept; unique_ptr(pointer p, see below d2) noexcept; unique_ptr(unique_ptr&& u) noexcept; constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { } template <class U, class E> unique_ptr(unique_ptr<U, E>&& u) noexcept; template <class U> unique_ptr(auto_ptr<U>&& u) noexcept; // 20.7.1.2.2, destructor ~unique_ptr(); // 20.7.1.2.3, assignment unique_ptr& operator=(unique_ptr&& u) noexcept; template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept; unique_ptr& operator=(nullptr_t) noexcept; // 20.7.1.2.4, observers typename add_lvalue_reference<T>::type operator*() const; pointer operator->() const noexcept; pointer get() const noexcept; deleter_type& get_deleter() noexcept; const deleter_type& get_deleter() const noexcept; explicit operator bool() const noexcept; // 20.7.1.2.5 modifiers pointer release() noexcept; void reset(pointer p = pointer()) noexcept; void swap(unique_ptr& u) noexcept; // disable copy from lvalue unique_ptr(const unique_ptr&) = delete; unique_ptr& operator=(const unique_ptr&) = delete; }; }
1.模板参数D的默认类型是default_delete. 用户提供的模板参数D应为函数对象类型(20.8), 对函数的左值引用或对函数对象类型的左值引用, 给定值d为类型D, 值ptr为unique_ptr::pointer,则表达式d(ptr)有效, 并具有针对该deleter合适地释放指针的作用.
2.如果deleter的类型D不是引用类型, D应满足Destructible(Table 24)的要求.
3.如果类型remove_reference<D>::type::pointer 存在, 那么unique_ptr<T, D>::pointer应与remove_reference<D>::type::pointer同义. 否则, unique_ptr<T, D>::pointer应与T*同义. unique_ptr<T, D>::pointer 应满足NullablePointer(17.6.3.3)的要求.
4.[Example: 给定分配器类型X(17.6.3.5), 并让A为allocator_traits<X>的同义词, 类型A::pointer, A::const_pointer, A::void_pointer和A::const_void_pointer可以用作unique_ptr<T,D>::pointer. -end example]
20.7.1.2.1 unique_ptr constructors
constexpr unique_ptr() noexcept;
1.要求: D应满足DefaultConstructible(Table 19),并且构造函数不应抛出异常.
2.作用: 构造一个unique_ptr对象, 其不用有任何内容, 值初始化存储的指针和deleter.
3.后置条件: get() == nullptr. get_deleter()返回对存储的deleter的引用.
4.备注: 如果使用指针类型或模板参数D的引用类型实例化此构造函数, 程序ill-formed.
explicit unique_ptr(pointer p) noexcept;
5.要求: D应满足DefaultConstructible(Table 19)的要求, 并且构造函数不应抛出异常.
6.作用: 构造一个unique_ptr对象, 其拥有p, 用p初始化存储的指针, 值初始化存储的deleter.
7.后置条件: get() == p. get_deleter()返回对存储的deleter的引用.
8.备注: 如果使用指针类型或模板参数D的引用类型实例化此构造函数, 程序ill-formed.
unique_ptr(pointer p, see below d1) noexcept;
unique_ptr(pointer p, see below d2) noexcept;
9.这些构造函数的签名(signature)依赖D是否是一个引用类型. 如果D是非引用类型A, 那么签名是:
- unique_ptr(pointer p, const A& d);
- unique_ptr(pointer p, A&& d);
10.如果D是左值引用类型A& , 那么签名是:
- unique_ptr(pointer p, A& d);
- unique_ptr(pointer p, A&& d);
11.如果D是左值引用类型const A&, 那么签名是:
- unique_ptr(pointer p, const A& d);
- unique_ptr(pointer p, const A&& d);
12.要求:
如果D不是左值引用类型,那么
如果d是左值或const右值, 那么选择第一个构造函数. D应满足CopyConstructible(Table 21)的要求, 并且D的copy构造函数禁止抛出异常. 这个unique_ptr持有d的copy.
否则, d是非const右值引用, 选择第二个构造函数. D应满足MoveConstructible(Table 20)的要求, 并且D的move构造函数禁止抛出异常. 这个unique_ptr持有从d移动构造的值.
否则, D是一个左值引用类型. d应和其中一个构造函数兼容. 如果d是一个右值, 选择第二个构造函数, 并且程序ill-formed. [Note: 可以使用static_assert来诊断,以确保D不是引用类型. -end note] 否则,d是一个左值, 选择第一个构造函数. D引用的类型不必是CopyConstructible或MoveConstructible. 这个unique_ptr保存一个引用左值d的D类型对象.[Note: D可能不是右值引用类型. -end note]
13.作用: 构造一个unique_ptr对象, 其持有p, 用p初始化存储的指针, 按如上所述初始化deleter.
14.后置条件: get() == p. get_deleter() 返回对存储的deleter的引用. 如果D是引用类型, 那么get_deleter()返回对左值d的引用.
[Example: D d;
unique_ptr<int, D> p1(new int, D()); // D must be MoveConstructible unique_ptr<int, D> p2(new int, d); // D must be Copyconstructible unique_ptr<int, D&> p3(new int, d); // p3 holds a reference to d unique_ptr<int, const D&> p4(new int, D()); // error: rvalue deleter object combined // with reference deleter type -end example]
unique_ptr(unique_ptr&& u) noexcept;
15.要求: 如果D不是引用类型, D应满足MoveConstructible(Table 20)的要求.从类型D的右值构造deleter不应引发异常.
16.作用: 通过从u转移所有权到this来构造unique_ptr. 如果D是引用类型, 这个deleter从u的deleter copy构造;否则, 移动构造. [Note: deleter构造函数可能用std::forward<D>实现. -end note*]
17.后置条件: 在构造之前get()返回u.get()的值.(get() yields the value u.get() yielded before the construction.) get_deleter()返回对存储的deleter的引用, deleter从u.get_deleter()构造. 如果D是引用类型, 那么get_deleter()和u.get_deleter()引用相同的左值deleter.
template <class U, class E> unique_ptr(unique_ptr<U, E>&& u) noexcept;
18.要求: 如果E不是引用类型, 从类型E的右值deleter的构造应well-formed, 并且不抛出异常. E是引用类型, 并且从类型E的左值deleter的构造应well_formed, 并且不抛出异常.
19.备注: 这个构造函数不参与重载决议, 除非:
- unique_ptr<U, E>::pointer可隐式转换为pointer.
- U不是数组类型
- D是引用类型, E是与D相同的类型, 或者D不是引用类型, 并且E可以隐式转换为D.
20.作用: 通过从u转移所有权到this来构造unique_ptr. 如果E是引用类型, 这个deleter从u的deleter copy构造;否则, 移动构造. [Note: deleter构造函数可能用std::forward<D>实现. -end note*]
21.后置条件: 在构造之前get()返回u.get()的值. get_deleter()返回对存储的deleter的引用, deleter从u.get_deleter()构造.
template <class U> unique_ptr(auto_ptr<U>&& u) noexcept;
(C++17中移除)
20.7.1.2.2 unique_ptr destructor
~unique_ptr();
1.要求: 表达式get_deleter()(get())应well formed, 有良好定义的行为, 不抛出异常. [Note: default_delete的使用要求T是完整的类型. -end note]
2.作用: 如果 get() == nullptr, 无作用. 否则, get_deleter()(get()).
20.7.1.2.3 unique_ptr assignment
unique_ptr& operator=(unique_ptr&& u) noexcept;
1.要求: 如果D不是引用类型, D应满足MoveAssignable(Table 22)和类型D的右值deleter的assignment不会抛出异常. 否则, D是引用类型, remove_reference<D>::type 应满足CopyAssignment要求和类型D的左值deleter的assignment不会抛出异常.
2.作用: 将所有权从u转移到*this, 如同以调用reset(r.release())后调用get_deleter()到std::forward<E>(r.get_deleter())的赋值.
3.返回值: *this.
template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
4.要求: 如果E不是引用类型, E类型的右值deleter的assignment应well-formed并且不抛出异常. 否则, E是引用类型, E类型左值deleter的assignment应well-formed并且不抛出异常.
5.备注: 这个运算符不参与重载决议, 除非:
- unique_ptr<U, E>::pointer可隐式转换成pointer
- U不是数组类型
6.作用: 将所有权从u转移到*this, 如同以调用reset(r.release())后调用get_deleter()到std::forward<E>(r.get_deleter())的赋值.
7.返回值: *this.
unique_ptr& operator=(nullptr_t) noexcept;
8.作用: reset().
9.后置条件: get() == nullptr.
10.返回值: *this.
20.7.1.2.4 unique_ptr observers
typename add_lvalue_reference<T>::type operator*() const;
1.要求: get() != nullptr.
2.返回值: *get().
pointer operator->() const noexcept;
3.要求: get() != nullptr.
4.返回值: get().
5.Note: 使用通常要求T是完整类型.
pointer get() const noexcept;
6.返回值: 存储的指针.
deleter_type& get_deleter() noexcept;
const deleter_type& get_deleter() const noexcept;
7.返回值: 存储的deleter的引用.
explicit operator bool() const noexcept;
8.返回值: get() != nullptr.
20.7.1.2.5 unique_ptr modifiers
pointer release() noexcept;
1.后置条件: get() == nullptr.
2.返回值: get()值在release调用的开始处.
(The value get() had at the start of the call to release.)
// 只是释放管理权, 需要手动调用delete.
void reset(pointer p = pointer()) noexcept;
3.要求: get_deleter()(get())应well formed, 有良好定义的行为, 禁止抛出异常.
4.作用: 用p对存储的指针赋值, old_p表示旧值且不等于nullptr, 调用get_deleter()(old_p). [Note: 这些操作的顺序很重要, 因为对get_deleter()的调用可能会析构this. -end note*]
5.后置条件: get() == p. [Note: 如果get_deleter()会析构*this, 则此条件不成立, 因为this->get()不再是有效的表达式. -end note]
void swap(unique_ptr& u) noexcept;
6.要求: get_deleter()应可交换, 并且swap下不抛出异常.
7.作用: 交换*this和u中存储的指针和deleter.
20.7.1.3 unique_ptr for array objects with a runtime length
namespace std { template <class T, class D> class unique_ptr<T[], D> { public: typedef see below pointer; typedef T element_type; typedef D deleter_type; // 20.7.1.3.1, constructors constexpr unique_ptr() noexcept; explicit unique_ptr(pointer p) noexcept; unique_ptr(pointer p, see below d) noexcept; unique_ptr(pointer p, see below d) noexcept; unique_ptr(unique_ptr&& u) noexcept; constexpr unique_ptr(nullptr_t) : unique_ptr() { } // destructor ~unique_ptr(); // assignment unique_ptr& operator=(unique_ptr&& u) noexcept; unique_ptr& operator=(nullptr_t) noexcept; // 20.7.1.3.2, observers T& operator[](size_t i) const; pointer get() const noexcept; deleter_type& get_deleter() noexcept; const deleter_type& get_deleter() const noexcept; explicit operator bool() const noexcept; // 20.7.1.3.3 modifiers pointer release() noexcept; void reset(pointer p = pointer()) noexcept; void reset(nullptr_t) noexcept; template <class U> void reset(U) = delete; void swap(unique_ptr& u) noexcept; // disable copy from lvalue unique_ptr(const unique_ptr&) = delete; unique_ptr& operator=(const unique_ptr&) = delete; }; }
1.数组类型的特化提供了稍微改变的接口.
- 在unique_ptr<T[], D>的不同类型之间或者到unique_ptr的非数组形式或从非数组形式的unique_ptr转换使得程序ill-formed.
- 指向从T派生的指针被构造函数拒绝, 并reset.
- 不提供观察器operator*和operator->.
- 提供index访问 operator[].
- 默认deleter会调用delete[].
2.下面仅对具有与主模板不同行为的成员函数提供描述.
3.模板参数T应是完整类型.
20.7.1.3.1 unique_ptr constructors
explicit unique_ptr(pointer p) noexcept;
unique_ptr(pointer p, see below d) noexcept;
unique_ptr(pointer p, see below d) noexcept;
这些构造函数表现得和主模板中一样, 除了它们不接受可转换为pointer的指针类型. [Note: 一种实现技术是通过创建这些成员的private模板化的重载. -end note]
20.7.1.3.2 unique_ptr observers
T& operator[](size_t i) const;
1.要求: i < 存储的指针指向的数组中的元素数量.
2.返回值: get()[i].
20.7.1.3.3 unique_ptr modifiers
void reset(pointer p = pointer()) noexcept;
void reset(nullptr_t p) noexcept;
1.作用: 如果get() == nullptr, 无作用;否则, get_deleter()(get()).
2.后置条件: get() == p.
20.7.1.4 unique_ptr specialized algorithms
template <class T, class D> void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept;
1.作用: 调用x.swap(y)
template <class T1, class D1, class T2, class D2>
bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
2.返回值: x.get() == y.get()
template <class T1, class D1, class T2, class D2>
bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
3.返回值: x.get() != y.get()
template <class T1, class D1, class T2, class D2>
bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
4.要求: 令CT为common_type<unique_ptr<T1, D1>::pointer, unique_ptr<T2, D2>::pointer>::type. less<CT>的特化应是一个函数对象类型(20.8), 该函数对象类型对指针值产生严格的弱排序(25.4).
5.返回值: less<CT>()(x.get(), y.get())
6.备注: 如果unique_ptr<T1, D1>::pointer 不可隐式转换成CT 或unique_ptr<T2, D2>::pointer不可隐式转换成CT, 程序ill-formed.
template <class T1, class D1, class T2, class D2>
bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
7.返回值: !(y < x)
template <class T1, class D1, class T2, class D2>
bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
8.返回值: y < x
template <class T1, class D1, class T2, class D2>
bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
9.返回值: !(x < y)
template <class T, class D> bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;
template <class T, class D> bool operator==(nullptr_t, const unique_ptr<T, D>& x) noexcept;
10.返回值: !x
template <class T, class D> bool operator!=(const unique_ptr<T, D>& x, nullptr_t) noexcept;
template <class T, class D> bool operator!=(nullptr_t, const unique_ptr<T, D>& x) noexcept;
11.返回值: (bool)x
template <class T, class D> bool operator<(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D> bool operator<(nullptr_t, const unique_ptr<T, D>& x);
12.要求: less<unique_ptr<T, D>::pointer>应是一个函数对象类型, 该函数对象类型对指针值产生严格的弱排序.
13.返回值: 第一个模板函数返回less<unique_ptr<T, D>::pointer>()(x.get(), nullptr). 第二个模板函数返回less<unique_ptr<T, D>::pointer>()(nullptr, x.get()).
template <class T, class D> bool operator>(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D> bool operator>(nullptr_t, const unique_ptr<T, D>& x);
14.返回值: 第一个模板函数返回 nullptr < x. 第二个模板函数返回 x < nullptr.
template <class T, class D> bool operator<=(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D> bool operator<=(nullptr_t, const unique_ptr<T, D>& x);
15.返回值: 第一个模板函数返回 !(nullptr < x). 第二个模板函数返回 !(x < nullptr).
template <class T, class D> bool operator>=(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D> bool operator>=(nullptr_t, const unique_ptr<T, D>& x);
16.返回值: 第一个模板函数返回 !(x < nullptr). 第二个模板函数返回 !(nullptr < x).
20.7.2 Shared-ownership pointers
20.7.2.1 Class bad_weak_ptr
namespace std { class bad_weak_ptr: public std::exception { public: bad_weak_ptr() noexcept; }; } // namespace std
1.shared_ptr构造函数采用了weak_ptr抛出bad_weak_ptr类型的异常.
bad_weak_ptr() noexcept;
2.后置条件: what() 返回 "bad_weak_ptr".
20.7.2.2 Class template shared_ptr
1.shared_ptr类模板存储一个通常由new获得的指针. shared_ptr实现共享所有权的语义;最后一个某指针所有者有责任释放指针, 或以其他方式释放与存储的指针关联的资源. 如果不持有一个指针, shared_ptr对象empty.
namespace std{ template<class T> class shared_ptr{ public: typedef T element_type; // 20.7.2.2.1, constructors: constexpr shared_ptr() noexcept; template<class Y> explicit shared_ptr(Y* p); template<class Y, class D> shared_ptr(Y* p, D d); template<class Y, class D, class A> shared_ptr(Y* p, D d, A a); template <class D> shared_ptr(nullptr_t p, D d); template <class D, class A> shared_ptr(nullptr_t p, D d, A a); template<class Y> shared_ptr(const shared_ptr<Y>& r, T *p) noexcept; shared_ptr(const shared_ptr& r) noexcept; template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept; shared_ptr(shared_ptr&& r) noexcept; template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept; template<class Y> explicit shared_ptr(const weak_ptr<Y>& r); template<class Y> shared_ptr(auto_ptr<Y>&& r); template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r); constexpr shared_ptr(nullptr_t) : shared_ptr() { } // 20.7.2.2.2, destructor: ~shared_ptr(); // 20.7.2.2.3, assignment: shared_ptr& operator=(const shared_ptr& r) noexcept; template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept; shared_ptr& operator=(shared_ptr&& r) noexcept; template<class Y> shared_ptr& operator=(shared_ptr<Y>&& r) noexcept; template<class Y> shared_ptr& operator=(auto_ptr<Y>&& r); template <class Y, class D> shared_ptr& operator=(unique_ptr<Y, D>&& r); // 20.7.2.2.4, modifiers: void swap(shared_ptr& r) noexcept; void reset() noexcept; template<class Y> void reset(Y* p); template<class Y, class D> void reset(Y* p, D d); template<class Y, class D, class A> void reset(Y* p, D d, A a); // 20.7.2.2.5, observers: T* get() const noexcept; T& operator*() const noexcept; T* operator->() const noexcept; long use_count() const noexcept; bool unique() const noexcept; explicit operator bool() const noexcept; template<class U> bool owner_before(shared_ptr<U> const& b) const; template<class U> bool owner_before(weak_ptr<U> const& b) const; }; // 20.7.2.2.6, shared_ptr creation template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args); template<class T, class A, class... Args> shared_ptr<T> allocate_shared(const A& a, Args&&... args); // 20.7.2.2.7, shared_ptr comparisons: template<class T, class U> bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator<(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator>(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator<=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator>=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template <class T> bool operator==(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator==(nullptr_t, const shared_ptr<T>& b) noexcept; template <class T> bool operator!=(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator!=(nullptr_t, const shared_ptr<T>& b) noexcept; template <class T> bool operator<(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator<(nullptr_t, const shared_ptr<T>& b) noexcept; template <class T> bool operator<=(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator<=(nullptr_t, const shared_ptr<T>& b) noexcept; template <class T> bool operator>(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator>(nullptr_t, const shared_ptr<T>& b) noexcept; template <class T> bool operator>=(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator>=(nullptr_t, const shared_ptr<T>& b) noexcept; // 20.7.2.2.8, shared_ptr specialized algorithms: template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept; // 20.7.2.2.9, shared_ptr casts: template<class T, class U> shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept; // 20.7.2.2.10, shared_ptr get_deleter: template<class D, class T> D* get_deleter(const shared_ptr<T>& p) noexcept; // 20.7.2.2.11, shared_ptr I/O: template<class E, class T, class Y> basic_ostream<E, T>& operator<< (basic_ostream<E, T>& os, const shared_ptr<Y>& p); } // namespace std
2.shared_ptr的特化应是CopyConstructible,CopyAssignable,和LessThanComparable, 以允许它们在标准容器中使用. shared_ptr的特化应可转换为bool, 以允许它们在条件中的bool表达式和声明中使用. 模板参数T可以是未完成类型.
3.[Example: if(shared_ptr<X> px = dynamic_pointer_cast<X>(py)){ // 使用px } -end example]
4.为了确定是否存在数据竞争, 成员函数应仅访问和修改shared_ptr和weak_ptr对象本身, 而不能访问和修改它们所引用的对象. use_count()中的更改不会作用可能引起数据竞争的修改.
20.7.2.2.1 shared_ptr constructors
constexpr shared_ptr() noexcept;
1.作用: 构造一个empty shared_ptr对象.
2.后置条件: use_count() == 0 && get() == 0.
template<class Y> explicit shared_ptr(Y* p);
3.要求: p应可转换为T*. Y应是完整类型. 表达式delete p应well formed, 并且有良好定义行为, 并且不抛出异常.
4.作用: 构造一个持有指针p的shared_ptr对象.
5.后置条件: use_count() == 1 && get() == p.
6.Throws: bad_alloc, 或者当无法获得除内存以外的资源时, 实现定义的异常.
7.异常安全: 如果抛出异常, delete p被调用.
template<class Y, class D> shared_ptr(Y* p, D d);
template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);
template <class D> shared_ptr(nullptr_t p, D d);
template <class D, class A> shared_ptr(nullptr_t p, D d, A a);
8.要求: p应可转换为T*. D应是CopyConstructible. D的copy构造函数和析构函数禁止抛出异常. 表达式d(p) 应well formed,有良好定义的行为, 不抛出异常. A应是一个allocator(17.6.3.5). A的copy构造函数和析构函数禁止抛出异常.
9.作用: 构造一个持有指针p和deleter d的shared_ptr对象. 第二个和第四个构造函数应使用a的copy来为内部使用分配内存.
10.后置条件: use_count() == 1 && get() == p.
11.Throws: bad_alloc, 或当无法获得除内存以外的资源时,实现定义的异常.
12.异常安全: 如果抛出异常, 调用d(p).
template<class Y> shared_ptr(const shared_ptr<Y>& r, T *p) noexcept;
13.作用: 构造存储p的shared_ptr对象, 和r共享所有权.
14.后置条件: get() == p && use_count() == r.use_count()
15.[Note: 为避免指针悬空的可能性, 此构造函数的用户必须确保p至少在r的所有权组被破坏之前保持有效. -end note]
16.[Note: 该构造函数允许创建一个带有非NULL存储指针的空shared_ptr实例. -end note]
shared_ptr(const shared_ptr& r) noexcept;
template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;
17.要求: 第二个构造函数不参与重载决议, 除非Y*可隐式转换为T*.
18.作用: 如果r empty,构造一个empty shared_ptr对象; 否则, 构造一个和r共享所有权的shared_ptr对象.
19.后置条件: get() == r.get() && use_count() == r.use_count()
shared_ptr(shared_ptr&& r) noexcept;
template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept;
20.备注: 第二个构造函数不参与重载决议, 除非Y*可隐式转换为T*.
21.作用: 从r移动构造一个shared_ptr对象.
22.后置条件: *this应包含r的旧值. r为empty. r.get() == 0.
template<class Y> explicit shared_ptr(const weak_ptr<Y>& r);
23.要求: Y*可转换为T*.
24.作用: 构造与r共享所有权的shared_ptr, 其存储r中存储的指针的copy.
25.后置条件: use_count() == r.use_count()
26.Throws: 当r.expired(), bad_weak_ptr
27.异常安全: 如果抛出异常, 此构造函数无作用.
template<class Y> shared_ptr(auto_ptr<Y>&& r);
C++17移除.
template <class Y, class D> shared_ptr(unique_ptr<Y, D>&&r);
33.作用: 当D不是引用类型时,等价于shared_ptr(r.release(), r.get_deleter()); 否则shared_ptr(r.release(), ref(r.get_deleter()))
34.异常安全: 如果抛出异常, 此构造函数无作用.
20.7.2.2.2 shared_ptr destructor
~shared_ptr();
1.作用:
- 如果*this为空或和其他shared_ptr实例共享所有权(use_count() > 1), 没有副作用.
- 否则, 如果*this拥有对象(原文是object, 应该是pointer)p和deleter d, 调用d(p).
- 否则, *this 拥有指针p, 调用delete p.
2.[Note: 由于*this的析构函数减少喝*this共享所有权的实例数量减1, 在*this被析构后, 与*this共享所有权的所有shared_ptr实例将report一个use_count(), 该值比先前的值少1. -end note]
20.7.2.2.3 shared_ptr assignment
shared_ptr& operator=(const shared_ptr& r) noexcept;
template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;
template<class Y> shared_ptr& operator=(auto_ptr<Y>&& r);
1.作用: 等效于shared_ptr(r).swap(*this).
2.返回值: *this
3.[Note: 由于临时对象的构造和析构导致的use count更新不是可观察到的副作用, 因此, 实现可能会通过不同的方式满足作用(和隐式的保证), 而不会产生临时对象. 尤其是:
shared_ptr<int> p(new int); shared_Ptr<void> q(p); p=p; q=p;
两个赋值可能都是无操作的.-end note]
shared_ptr& operator=(shared_ptr&& r) noexcept;
template<class Y> shared_ptr& operator=(shared_ptr<Y>&& r) noexcept;
4.作用: 等效于shared_ptr(std::move(r)).swap(*this).
5.返回值: *this
template <class Y, class D> shared_ptr& operator=(unique_ptr<Y, D>&& r);
6.作用: 等效于shared_ptr(std::move(r)).swap(*this).
7.返回值: *this
20.7.2.2.4 shared_ptr modifiers
void swap(shared_ptr& r) noexcept;
1.作用: 交换*this和r的内容.
void reset() noexcept;
2.作用: 等效于shared_ptr().swap(*this)
template<class Y> void reset(Y* p);
3.作用: 等效于shared_ptr(p).swap(*this)
template<class Y, class D> void reset(Y* p, D d);
4.作用: 等效于shared_ptr(p, d).swap(*this)
template<class Y, class D, class A> void reset(Y* p, D d, A a);
5.作用: 等效于shared_ptr(p, d, a).swap(*this)
20.7.2.2.5 shared_ptr observers
T* get() const noexcept;
1.返回值: 存储的指针.
T& operator*() const noexcept;
2.要求: get() != 0.
3.返回值: *get().
4.备注: T是void时, 未指定是否此成员函数会被声明. 如果被声明, 未指定返回值, 除了函数的声明(尽管不一定是定义)必须格式正确.
T* operator->() const noexcept;
5.要求: get() != 0
6.返回值: get()
long use_count() const noexcept;
7.返回值: 与*this共享所有权的shared_ptr对象的数量, 包括*this , 或当*this为空时, 0.
8.[Note: use_count()不一定有效. -end note]
bool unique() const noexcept;
C++17弃用, 20移除.因为先前拥有者对被管理对象的访问可能未完成, 而因为新的共享拥有者可以同时引入.(析构函数和构造函数都可能在一定条件下立即实施, 导致use_count非1).
9.返回值: use_count() == 1.
10.[Note: unique()可能比use_count()快. 如果你正在使用unique()来实现copy-on-write, 当 get() == 0 时不依赖特定值. -end note]
explicit operator bool() const noexcept;
11.返回值: get() != 0.
template<class U> bool owner_before(shared_ptr<U> const& b) const;
template<class U> bool owner_before(weak_ptr<U> const& b) const;
12.返回值: 未指定的值:
- x.owner_before(y) 定义了像25.4中的严格弱排序.
- 在定义的对等关系下, owner_before, !a.owner_before(b) && !b.owner_before(a), 当且仅当两个shared_ptr或weak_ptr实例共享所有权或都为空时, 他们是等效的.
20.7.2.2.6 shared_ptr creation
template<class T, class... Args>
shared_ptr<T> make_shared(Args&&... args);
template<class T, class A, class... Args>
shared_ptr<T> allocate_shared(const A& a, Args&&... args);
1.要求: 表达式::new(pv) T(std::forward<Args>(args)...) well formed, 其中pv是类型void*和指向 持有T类型对象的内存合适的 指针. A应是allocator(17.6.3.5).A的copy构造函数和析构函数禁止抛出异常.
2.作用: 分配与类型T对象合适的内存并且在此内存通过placement new 表达式::new(pv) T(std::forward<Args>(arg)...)构造对象. 模板allocate_shared使用a的copy来分配内存. 如果抛出异常, 此函数无作用.
3.返回值: shared_ptr实例, 该实例存储和拥有最新给构造的类型T对象的地址.
4.后置条件: get() != 0 && use_count() == 1
5.Throws: bad_alloc,或从A::allocate或T的构造函数抛出的异常.
6.备注: 建议实现,但不是必须的,执行不超过一个的内存分配. [Note: 这提供了等效于侵入式智能指针的效率. -end note]
7.[Note: 这些函数通常会分配比sizeof(T)更多的内存,以允许内部记录结构(例如引用计数). -end note]
20.7.2.2.7 shared_ptr comparison
template<class T, class U>
bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
1.返回值: a.get() == b.get()
template<class T, class U>
bool operator<(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
2.返回值: less<V>()(a.get(), b.get()),其中V是T*和U*的综合指针类型.
3.[Note: 定义比较运算符可以将shared_ptr对象用作关联容器中的key. -end note]
template <class T> bool operator==(const shared_ptr<T>& a, nullptr_t) noexcept;
template <class T> bool operator==(nullptr_t, const shared_ptr<T>& a) noexcept;
4.返回值: !a
template <class T> bool operator!=(const shared_ptr<T>& a, nullptr_t) noexcept;
template <class T> bool operator!=(nullptr_t, const shared_ptr<T>& a) noexcept;
5.返回值: (bool)a
template <class T> bool operator<(const shared_ptr<T>& a, nullptr_t) noexcept;
template <class T> bool operator<(nullptr_t, const shared_ptr<T>& a) noexcept;
6.返回值: 第一个模板函数返回less<T>()(a.get(), nullptr). 第二个模板函数返回less<T>()(nullptr, a.get()).
template <class T> bool operator>(const shared_ptr<T>& a, nullptr_t) noexcept;
template <class T> bool operator>(nullptr_t, const shared_ptr<T>& a) noexcept;
7.返回值: 第一个模板函数返回nullptr < a. 第二个模板函数返回a < nullptr.
template <class T> bool operator<=(const shared_ptr<T>& a, nullptr_t) noexcept;
template <class T> bool operator<=(nullptr_t, const shared_ptr<T>& a) noexcept;
8.返回值: 第一个模板函数返回 !(nullptr < a). 第二个模板函数返回 !(a < nullptr).
template <class T> bool operator>=(const shared_ptr<T>& a, nullptr_t) noexcept;
template <class T> bool operator>=(nullptr_t, const shared_ptr<T>& a) noexcept;
9.返回值: 第一个模板函数返回!(a < nullptr). 第二个模板函数返回!(nullptr < a).
20.7.2.2.8 shared_ptr specialized algorithms
template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept;
1.作用: 等效于a.swap(b).
20.7.2.2.9 shared_ptr cast
template<class T, class U>
shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept;
1.要求: 表达式static_cast<T*>(r.get())应well formed.
2.返回值: 如果r为empty,一个empty shared_ptr<T>;否则,一个存储static_cast<T*>(r.get())和与r共享所有权的shared_ptr<T>对象.
3.后置条件: w.get() == static_cast<T*>(r.get()) 并且 w.use_count() == r.use_count(),其中w是返回值.
4.[Note: 看似等效的表达式shared_ptr<T>(static_cast<T*>(r.get()))最终将导致尝试删除同一对象两次的未定义的行为. -end note]
template<class T, class U>
shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept;
5.要求: 表达式dynamic_cast<T*>(r.get())应well formed并且有良好行为.
6.返回值:
- 当dynamic_cast<T*>(r.get())返回非0值,一个存储其copy并与r共享所有权的shared_ptr<T>对象.
- 否则,一个empty shared_ptr<T>对象.
7.后置条件: w.get() == dynamic_cast<T*>(r.get()),其中w是返回值.
8.[Note: 看似等效的表达式shared_ptr<T>(dynamic_cast<T>(r.get()))最终将导致尝试删除同一对象两次的未定义行为. -end note*]
template<class T, class U>
shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept;
9.要求: 表达式const_cast<T*>(r.get())应well formed.
10.返回值: 如果r为empty,一个empty shared_ptr<T>;否则,一个存储const_cast<T*>(r.get())并与r共享所有权的shared_ptr<T>.
11.后置条件: w.get() == const_cast<T*>(r.get()) 并且 w.use_count() == r.use_count(),其中w是返回值.
12.[Note: 看似等效的表达式shared_ptr<T>(const_cast<T>(r.get()))最终将导致尝试删除同一对象两次的未定义行为. -end note*]
20.7.2.2.10 get_deleter
template<class D, class T>
D* get_deleter(const shared_ptr<T>& p) noexcept;
1.返回值: 如果p拥有无cv限定的deleter d,返回&d;否则返回0. 只要存在一个拥有d的shared_ptr实例,返回的指针就保持有效. [Note: 未指定超过此时间指针是否保持有效.如果实现析构deleter直到所有共享p的所有权的weak_ptr实例被析构. -end note]
20.7.2.2.11 shared_ptr I/O
template<class E, class T, class Y>
basic_ostream<E, T>& operator<< (basic_ostream<E, T>& os, shared_ptr<Y> const& p);
1.作用: os<<p.get().
2.返回值: os.
20.7.2.3 Class template weak_ptr
1.weak_ptr类模板存储一个已经被shared_ptr管理的对象的弱引用.访问此对象,weak_ptr通过成员函数lock可转换为shared_ptr.
namespace std { template<class T> class weak_ptr { public: typedef T element_type; // 20.7.2.3.1, constructors constexpr weak_ptr() noexcept; template<class Y> weak_ptr(shared_ptr<Y> const& r) noexcept; weak_ptr(weak_ptr const& r) noexcept; template<class Y> weak_ptr(weak_ptr<Y> const& r) noexcept; // 20.7.2.3.2, destructor ~weak_ptr(); // 20.7.2.3.3, assignment weak_ptr& operator=(weak_ptr const& r) noexcept; template<class Y> weak_ptr& operator=(weak_ptr<Y> const& r) noexcept; template<class Y> weak_ptr& operator=(shared_ptr<Y> const& r) noexcept; // 20.7.2.3.4, modifiers void swap(weak_ptr& r) noexcept; void reset() noexcept; // 20.7.2.3.5, observers long use_count() const noexcept; bool expired() const noexcept; shared_ptr<T> lock() const noexcept; template<class U> bool owner_before(shared_ptr<U> const& b); template<class U> bool owner_before(weak_ptr<U> const& b); }; // 20.7.2.3.6, specialized algorithms template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept; } // namespace std
2.weak_ptr特化应CopyConstructible和CopyAssignable,以允许在标准容器中使用. weak_ptr的模板参数T可能是未完成类型.
20.7.2.3.1 weak_ptr constructors
constexpr weak_ptr() noexcept;
1.作用: 构造empty weak_ptr对象.
2.后置条件: use_count() == 0.
weak_ptr(const weak_ptr& r) noexcept;
template<class Y> weak_ptr(const weak_ptr<Y>& r) noexcept;
template<class Y> weak_ptr(const shared_ptr<Y>& r) noexcept;
3.要求: 第二和第三个构造函数不参与重载决议,除非Y*可隐式转换为T*.
4.作用: 如果r为empty,构造empty weak_ptr对象;否则,构造一个与r共享所有权且存储r中指针的copy的weak_ptr对象.
5.后置条件: use_count() == r.use_count().
20.7.2.3.2 weak_ptr destructor
~weak_ptr();
1.作用: 析构weak_ptr对象但对其存储的指针指向的对象无作用.
20.7.2.3.3 weak_ptr assignment
weak_ptr& operator=(const weak_ptr& r) noexcept;
template<class Y> weak_ptr& operator=(const weak_ptr<Y>& r) noexcept;
template<class Y> weak_ptr& operator=(const shared_ptr<Y>& r) noexcept;
1.作用: 等效于weak_ptr(r).swap(*this).
2.备注: 实现可以通过不产生临时对象的不同方式满足作用(和隐含的保证).
20.7.2.3.4 weak_ptr modifiers
void swap(weak_ptr& r) noexcept;
1.作用: 交换*this和r的内容.
void reset() noexcept;
2.作用: 等效于weak_ptr().swap(*this).
20.7.2.3.5 weak_ptr observers
long use_count() const noexcept;
1.返回值: 如果*this empty,0;否则,共享*this所有权的shared_ptr实例的个数.
2.[Note: use_count()不一定有效. -end note]
bool expired() const noexcept;
3.返回值: use_count() == 0.
4.[Note: expired()可能比use_count()快. -end note]
shared_ptr<T> lock() const noexcept;
5.返回值: expired() ? shared_ptr<T>() : shared_ptr<T>(*this);
template<class U> bool owner_before(shared_ptr<U> const& b);
template<class U> bool owner_before(weak_ptr<U> const& b);
6.返回值: 一个未指定的值:
- x.owner_before(y)定义严格弱排序.
- 在owner_before,!a.owner_before(b) && !b.owner_before(a)定义的对等关系下,当且仅当两个shared_ptr或weak_ptr实例共享所有权或都为空时,它们才是等效的.
20.7.2.3.6 weak_ptr specialized algorithms
template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;
1.作用: 等效于a.swap(b).
20.7.2.3.7 Class template owner_less
1.类模板owner_less允许对shared_ptr和weak_ptr进行基于所有权的混合比较.
namespace std { template<class T> struct owner_less; template<class T> struct owner_less<shared_ptr<T> > { typedef bool result_type; typedef shared_ptr<T> first_argument_type; typedef shared_ptr<T> second_argument_type; bool operator()(shared_ptr<T> const&, shared_ptr<T> const&) const; bool operator()(shared_ptr<T> const&, weak_ptr<T> const&) const; bool operator()(weak_ptr<T> const&, shared_ptr<T> const&) const; }; template<class T> struct owner_less<weak_ptr<T> > { typedef bool result_type; typedef weak_ptr<T> first_argument_type; typedef weak_ptr<T> second_argument_type; bool operator()(weak_ptr<T> const&, weak_ptr<T> const&) const; bool operator()(shared_ptr<T> const&, weak_ptr<T> const&) const; bool operator()(weak_ptr<T> const&, shared_ptr<T> const&) const; }; }
2.operator()(x, y)应返回x.owner_before(y). [Note: 注意
- operator()定义严格弱排序.
- 在owner_before,!a.owner_before(b) && !b.owner_before(a)定义的对等关系下,当且仅当两个shared_ptr或weak_ptr实例共享所有权或都为空时,它们才是等效的. -end note]
20.7.2.4 Class template enable_shared_from_this
1.类T可以从enable_shared_from_this<T>继承来获得shared_from_this成员函数,这些成员函数获得指向*this的shared_ptr实例.
2.[Example:
struct X: public enable_shared_from_this<X>{ }; int main(){ shared_ptr<X> p(new X); shared_ptr<X> q = p->shared_from_this(); assert(p == q); assert((!(p < q ) && !(q < p)); // p和q共享所有权. }
-end example]
namespace std { template<class T> class enable_shared_from_this { protected: constexpr enable_shared_from_this() noexcept; enable_shared_from_this(enable_shared_from_this const&) noexcept; enable_shared_from_this& operator=(enable_shared_from_this const&) noexcept; ~enable_shared_from_this(); public: shared_ptr<T> shared_from_this(); shared_ptr<T const> shared_from_this() const; }; } // namespace std
3.enable_shared_from_this的模板参数T可能是未完成类型.
constexpr enable_shared_from_this() noexcept;
enable_shared_from_this(const enable_shared_from_this<T>&) noexcept;
4.作用: 构造enable_shared_from_this<T>对象.
enable_shared_from_this<T>& operator=(const enable_shared_from_this<T>&) noexcept;
5.返回值: *this.
~enable_shared_from_this();
6.作用: 析构*this.
shared_ptr<T> shared_from_this();
shared_ptr<T const> shared_from_this() const;
7.要求: enable_shared_from_this<T>应是T的可访问基类.*this应是类型T的对象t的子对象.至少应有一个拥有&t的shared_ptr实例p.
8.返回值: 与p共享所有权的shared_ptr<T>对象r.
9.后置条件: r.get() == this.
10.[Note:
template<class T> class enable_shared_from_this { private: weak_ptr<T> __weak_this; protected: constexpr enable_shared_from_this() : __weak_this() { } enable_shared_from_this(enable_shared_from_this const &) { } enable_shared_from_this& operator=(enable_shared_from_this const &) { return *this; } ~enable_shared_from_this() { } public: shared_ptr<T> shared_from_this() { return shared_ptr<T>(__weak_this); } shared_ptr<T const> shared_from_this() const { return shared_ptr<T const>(__weak_this); } };
11.创建unique指针的shared_ptr的构造函数可以检测到enable_shared_from_this基础的存在,并将新创建的shared_ptr分配给其__weak_this成员. -end note]
20.7.2.5 shared_ptr atomic access
1.如果仅通过本节中的函数进行访问,并且实例作为其第一个参数传递,则从多个线程并发访问shared_ptr对象不会引起数据竞争.
2.类型memory_order参数的意义可参考29.3.
template<class T> bool atomic_is_lock_free(const shared_ptr<T>* p);
3.要求: p不能是null.
4.返回值: 如果原子访问*p是lock-free,true;否则false.
5.Throws: 无.
template<class T> shared_ptr<T> atomic_load(const shared_ptr<T>* p);
6.要求: p不能是null.
7.返回值: atomic_load_explicit(p, memory_order_seq_cst).
8.Throws: 无.
template<class T> shared_ptr<T> atomic_load_explicit(const shared_ptr<T>* p, memory_order mo);
9.要求: p不能是null.
10.要求: mo不能是memory_order_release或memory_order_acq_rel.
11.返回值: *p.
12.Throws: 无.
template<class T> void atomic_store(shared_ptr<T>* p, shared_ptr<T> r);
13.要求: p不能是null.
14.作用: atomic_store_explicit(p, r, memory_order_seq_cst).
15.Throws: 无.
template<class T> void atomic_store_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo);
16.要求: p不能是null.
17.要求: mo不能是memory_order_acquire或memory_order_acq_rel.
18.作用: p->swap(r).
19.Throws: 无.
template<class T> shared_ptr<T> atomic_exchange(shared_ptr<T>* p, shared_ptr<T> r);
20.要求: p不能是null.
21.返回值: atomic_exchange_explicit(p, r, memory_oder_seq_cst).
22.Thwors: 无.
template<class T> shared_ptr<T> atomic_exchange_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo);
23.要求: p不能是null.
24.作用: p->swap(r).
25.返回值: *p先前的值.
26.Throws: 无.
template<class T> bool atomic_compare_exchange_weak( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w);
27.要求: p不能是null.
28.返回值: atomic_compare_exchange_weak_explicit(p, v, w, memory_order_seq_cst, memory_order_seq,cst).
29.Throws: 无.
template<class T> bool atomic_compare_exchange_strong( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w);
30.返回值: atomic_compare_exchange_strong_explicit(p, v, w,memory_order_seq_cst, memory_order_seq_cst).
template<class T> bool atomic_compare_exchange_weak_explicit( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w, memory_order success, memory_order failure);
template<class T> bool atomic_compare_exchange_strong_explicit( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w, memory_order success, memory_order failure);
31.要求: p不能是null.
32.要求: failure不能是memory_order_release,memory_order_acq_rel,或强于success.
33.作用: 如果*p等于*v,则将w赋值给*p并具有与success值相对应的同步语义; 否则,将*p赋值给*v并具有与failure值相对应的同步语义.
34.返回值: 如果*p曾等于*v,true;否则false.
35.Throws: 无.
36.备注: 如果2个shared_ptr存储相同的指针值并共享所有权,它们对象等效.
37.备注: weak形式可能假失败.见29.6.
20.7.2.6 Smart pointer hash support
template<class T, class D> struct hash<unique_ptr<T, D>>;
1.要求: 模板特化应满足类模板hash(20.8.12)的要求.对类型UP的对象p来说,其中UP是unique_ptr<T, D>,hash<UP>()(p)应求得和hash<typename UP::pointer>()(p.get())同样的值. hash<typename UP::pointer>应well-formed.
template <class T> struct hash<shared_ptr<T> >;
2.要求: 模板特化应满足类模板hash(20.8.12)的要求.对shared_ptr<T>对象p来说,hash<shared_ptr<T>>()(p)应求得和hash<T*>()(p.get())一样的值.
20.8 Function objects
函数对象类型是对象类型(3.9),可以是函数调用中的后缀表达式的类型(5.2.2,13.3.1.1). 函数对象是函数对象类型的对象. 在人们期望将指向函数的指针传递到算法模板的地方(第25条),接口被指定为接受函数对象. 这不仅使算法模板可以使用指向函数的指针,而且还可以使它们与任意函数对象一起使用.
Header<functional> 概要
namespace std { // D.8.1, base (deprecated): template <class Arg, class Result> struct unary_function; template <class Arg1, class Arg2, class Result> struct binary_function; // 20.8.3, reference_wrapper: template <class T> class reference_wrapper; template <class T> reference_wrapper<T> ref(T&) noexcept; template <class T> reference_wrapper<const T> cref(const T&) noexcept; template <class T> void ref(const T&&) = delete; template <class T> void cref(const T&&) = delete; template <class T> reference_wrapper<T> ref(reference_wrapper<T>) noexcept; template <class T> reference_wrapper<const T> cref(reference_wrapper<T>) noexcept; // 20.8.4, arithmetic operations: template <class T> struct plus; template <class T> struct minus; template <class T> struct multiplies; template <class T> struct divides; template <class T> struct modulus; template <class T> struct negate; // 20.8.5, comparisons: template <class T> struct equal_to; template <class T> struct not_equal_to; template <class T> struct greater; template <class T> struct less; template <class T> struct greater_equal; template <class T> struct less_equal; // 20.8.6, logical operations: template <class T> struct logical_and; template <class T> struct logical_or; template <class T> struct logical_not; // 20.8.7, bitwise operations: template <class T> struct bit_and; template <class T> struct bit_or; template <class T> struct bit_xor; // 20.8.8, negators: template <class Predicate> class unary_negate; template <class Predicate> unary_negate<Predicate> not1(const Predicate&); template <class Predicate> class binary_negate; template <class Predicate> binary_negate<Predicate> not2(const Predicate&); // 20.8.9, bind: template<class T> struct is_bind_expression; template<class T> struct is_placeholder; template<class F, class... BoundArgs> unspecified bind(F&&, BoundArgs&&...); template<class R, class F, class... BoundArgs> unspecified bind(F&&, BoundArgs&&...); namespace placeholders { // M is the implementation-defined number of placeholders extern unspecified _1; extern unspecified _2; . . . extern unspecified _M; } // D.9, binders (deprecated): template <class Fn> class binder1st; template <class Fn, class T> binder1st<Fn> bind1st(const Fn&, const T&); template <class Fn> class binder2nd; template <class Fn, class T> binder2nd<Fn> bind2nd(const Fn&, const T&); // D.8.2.1, adaptors (deprecated): template <class Arg, class Result> class pointer_to_unary_function; template <class Arg, class Result> pointer_to_unary_function<Arg,Result> ptr_fun(Result (*)(Arg)); template <class Arg1, class Arg2, class Result> class pointer_to_binary_function; template <class Arg1, class Arg2, class Result> pointer_to_binary_function<Arg1,Arg2,Result> ptr_fun(Result (*)(Arg1,Arg2)); // D.8.2.2, adaptors (deprecated): template<class S, class T> class mem_fun_t; template<class S, class T, class A> class mem_fun1_t; template<class S, class T> mem_fun_t<S,T> mem_fun(S (T::*f)()); template<class S, class T, class A> mem_fun1_t<S,T,A> mem_fun(S (T::*f)(A)); template<class S, class T> class mem_fun_ref_t; template<class S, class T, class A> class mem_fun1_ref_t; template<class S, class T> mem_fun_ref_t<S,T> mem_fun_ref(S (T::*f)()); template<class S, class T, class A> mem_fun1_ref_t<S,T,A> mem_fun_ref(S (T::*f)(A)); template <class S, class T> class const_mem_fun_t; template <class S, class T, class A> class const_mem_fun1_t; template <class S, class T> const_mem_fun_t<S,T> mem_fun(S (T::*f)() const); template <class S, class T, class A> const_mem_fun1_t<S,T,A> mem_fun(S (T::*f)(A) const); template <class S, class T> class const_mem_fun_ref_t; template <class S, class T, class A> class const_mem_fun1_ref_t; template <class S, class T> const_mem_fun_ref_t<S,T> mem_fun_ref(S (T::*f)() const); template <class S, class T, class A> const_mem_fun1_ref_t<S,T,A> mem_fun_ref(S (T::*f)(A) const); // 20.8.10, member function adaptors: template<class R, class T> unspecified mem_fn(R T::*); template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...)); template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) const); template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) volatile); template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) const volatile); template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) &); template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) const &); template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) volatile &); template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) const volatile &); template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) &&); template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) const &&); template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) volatile &&); template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) const volatile &&); // 20.8.11 polymorphic function wrappers: class bad_function_call; template<class> class function; // undefined template<class R, class... ArgTypes> class function<R(ArgTypes...)>; template<class R, class... ArgTypes> void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&); template<class R, class... ArgTypes> bool operator==(const function<R(ArgTypes...)>&, nullptr_t); template<class R, class... ArgTypes> bool operator==(nullptr_t, const function<R(ArgTypes...)>&); template<class R, class... ArgTypes> bool operator!=(const function<R(ArgTypes...)>&, nullptr_t); template<class R, class... ArgTypes> bool operator!=(nullptr_t, const function<R(ArgTypes...)>&); // 20.8.12, hash function base template: template <class T> struct hash; // Hash function specializations template <> struct hash<bool>; template <> struct hash<char>; template <> struct hash<signed char>; template <> struct hash<unsigned char>; template <> struct hash<char16_t>; template <> struct hash<char32_t>; template <> struct hash<wchar_t>; template <> struct hash<short>; template <> struct hash<unsigned short>; template <> struct hash<int>; template <> struct hash<unsigned int>; template <> struct hash<long>; template <> struct hash<long long>; template <> struct hash<unsigned long>; template <> struct hash<unsigned long long>; template <> struct hash<float>; template <> struct hash<double>; template <> struct hash<long double>; template<class T> struct hash<T*>; }
[Example: 如果C++程序希望对两个包含double的vector a和b进行逐元素加法,然后将结果放入a中,则可以执行以下操作:
transform(a.begin(), a.end(), b.begin(), a.begin(), plus<double>());
-end example][Example: a的每个元素取反:
transform(a.begin(), a.end(), a.begin(), negate<double>());
-end example]为了使adaptors和其他组件能够处理带有一个或两个参数的函数对象,要求带有一个参数的函数对象相应地提供typedefs argument_type和result_type,带有两个参数的函数对象相应地提供first_argument_type,second_argument_type和result_type.
20.8.1 Definitions
1.以下定义用于本条款:
2.call signature是返回类型的名字,后跟用括号括住的逗号分隔的零个或多个参数类型列表.
3.callable type是函数对象类型或指向成员的指针.
4.callable object是一个可调用类型的对象.
5.call wrapper type是一种包含可调用对象并支持转发到该对象的调用操作类型.
6.call wrapper是call wrapper类型的一个对象.
7.target object 是由一个call wrapper保留的可调用对象.
20.8.2 Requirements
1.如下定义 INVOKE(f, t1, t2 ..., tN):
- (t1.*f)(t2, ..., tN),当f是某指向类成员函数的指针,t1是类型T的对象或类型T对象的引用或从T派生的类型对象t的引用时;
- ((t1).f)(t2, ..., tN),当f是指向类T的成员函数的指针,t1不是上一项中描述的类型之一;
- t1.*f,当 N == 1,f是指向类T的成员数据的指针,t1是类型T的对象或类型T对象的引用或从T派生的类型对象t的引用时;
- (t1).f,当 N == 1,f是指向类T的成员数据的指针,t1不是上一项中描述的类型之一;
- f(t1, t2, ..., tN),所有其他情况.
2.将INVOKE(f, t1, t2 ..., tN, R)定义为INVOKE(f, t1, t2, ..., tN)隐式转换为R.
3.如果call wrapper有个弱结果类型,那么其成员类型result_type是基于wrapper目标对象的类型T.
- 如果T指向函数类型,result_type应与T的返回值同义;
- 如果T指向成员函数,result_type应与T的返回值同义;
- 如果T是带有成员类型result_type的类,那么result_type应与T::result_type同义;
- 否则result_type将不被定义.
4.每个call wrapper应MoveConstructible.simple call wrapper是CopyConstructible和CopyAssignable的call wrapper,其copy构造函数,move构造函数和赋值运算符不会抛出异常. 转发call wrapper是可以使用任意参数列表调用的call wrapper,并将参数作为引用传递到wrapper的可调用对象. 该转发应确保右值参数作为右值引用传递,左值参数作为左值引用传递. [Note: 在典型的实现中,转发call wrapper具有以下形式的重载函数调用运算符:
template<class... UnBoundArgs\> R operator()(UnBoundArgs&&... unbound_args) cv-qual;
-end note]
20.8.3 Class template reference_wrapper
namespace std { template <class T> class reference_wrapper { public : // types typedef T type; typedef see below result_type; // not always defined typedef see below argument_type; // not always defined typedef see below first_argument_type; // not always defined typedef see below second_argument_type; // not always defined // construct/copy/destroy reference_wrapper(T&) noexcept; reference_wrapper(T&&) = delete; // do not bind to temporary objects reference_wrapper(const reference_wrapper<T>& x) noexcept; // assignment reference_wrapper& operator=(const reference_wrapper<T>& x) noexcept; // access operator T& () const noexcept; T& get() const noexcept; // invocation template <class... ArgTypes> typename result_of<T&(ArgTypes&&...)>::type operator() (ArgTypes&&...) const; }; }
1.reference_wrapper<T>是对类型T的对象或函数引用的CopyConstructible和CopyAssignable wrapper.
2.reference_wrapper<T>有weak result type.如果T是函数类型,result_type应与T的返回值同义.
3.reference_wrapper<T>的模板实例应定义内嵌具名类型argument_type作为T1的同义,当且仅当T符合下列条件之一:
- 若T为接受一个A1类型参数的函数或指向函数指针,则argument_type为A1.
- 若T是不接收参数的指向类T0成员函数的指针,则argument_type为T0*,可能有cv限定.
- 若T是拥有成员类型T::argument_type的类,则T1为argument_type.
4.模板实例化reference_wrapper必须有两个名为first_argument_type和second_argument_type的嵌套类型分别定义为T1和T2的同义,只有类型T为以下任何一种时:
- 若T为接收两个参数,类型分别是T1和T2的函数类型或指向函数类型指针.
- 指向成员函数指针R T0::f(T2) cv(可能有cv限定),T1是cv T0*.
- 若T是拥有拥有两个成员类型first_argument_type和second_argument_type的类;T1是T::first_argument_type,T2是T::second_argument_type.
(注:result_type,argument_tyope,first_argument_type,second_argument_type C++17 中弃用,C++20 中移除)
20.8.3.1 reference_wrapper construct/copy/destroy
reference_wrapper(T& t) noexcept;
1.作用: 构造存储引用t的reference_wrapper对象.
reference_wrapper(const reference_wrapper<T>& x) noexcept;
2.作用: 构造存储引用x.get()的reference_wrapper对象.
20.8.3.2 reference_wrapper assignment
reference_wrapper& operator=(const reference_wrapper<T>& x) noexcept;
1.后置条件: *this存储x.get()的引用.
20.8.3.3 reference_wrapper access
operator T& () const noexcept;
1.返回值: 存储的引用.
T& get() const noexcept;
2.返回值: 存储的引用.
20.8.3.4 reference_wrapper invocation
template <class... ArgTypes>
typename result_of<T&(ArgTypes&&... )>::type
operator()(ArgTypes&&... args) const;
1.返回值: INVOKE(get(), std::forward<ArgTypes>(args)...).
2.备注: 描述的operator()仅用于说明.不需要提供实际的reference_wrapper::operator()实现.允许实现通过多个重载运算符或其他方式支持reference_wrapper函数调用.
20.8.3.5 reference_wrapper helper functions
template <class T> reference_wrapper<T> ref(T& t) noexcept;
1.返回值: reference_wrapper<T>(t).
template <class T> reference_wrapper<T> ref(reference_wrapper<T>t) noexcept;
2.返回值: ref(t.get()).
template <class T> reference_wrapper<const T> cref(const T& t) noexcept;
3.返回值: reference_wrapper<const T>(t).
template <class T> reference_wrapper<const T> cref(reference_wrapper<T> t) noexcept;
4.返回值: cref(t.get()).
20.8.4 Arithmetic operations
1.该库为语言中的所有算术运算符提供了基本的函数对象类(5.6,5.7).
template <class T> struct plus { T operator()(const T& x, const T& y) const; typedef T first_argument_type; typedef T second_argument_type; typedef T result_type; };
2.operator() returns x + y.
template <class T> struct minus { T operator()(const T& x, const T& y) const; typedef T first_argument_type; typedef T second_argument_type; typedef T result_type; };
3.operator() returns x - y.
template <class T> struct multiplies { T operator()(const T& x, const T& y) const; typedef T first_argument_type; typedef T second_argument_type; typedef T result_type; };
4.operator() returns x * y.
template <class T> struct divides { T operator()(const T& x, const T& y) cons typedef T first_argument_type; typedef T second_argument_type; typedef T result_type; };
5.operator() returns x / y.
template <class T> struct modulus { T operator()(const T& x, const T& y) const; typedef T first_argument_type; typedef T second_argument_type; typedef T result_type; };
6.operator() returns x % y.
template <class T> struct negate { T operator()(const T& x) const; typedef T argument_type; typedef T result_type; };
7.operator() returns -x.
20.8.5 Comparisons
1.该库为语言中的所有比较运算符提供了基本的函数对象类(5.9,5.10).
template <class T> struct equal_to { bool operator()(const T& x, const T& y) const; typedef T first_argument_type; typedef T second_argument_type; typedef bool result_type; };
2.operator() returns x == y.
template <class T> struct not_equal_to { bool operator()(const T& x, const T& y) const; typedef T first_argument_type; typedef T second_argument_type; typedef bool result_type; };
3.operator() returns x != y.
template <class T> struct greater { bool operator()(const T& x, const T& y) const; typedef T first_argument_type; typedef T second_argument_type; typedef bool result_type; };
4.operator() returns x > y.
template <class T> struct less { bool operator()(const T& x, const T& y) const; typedef T first_argument_type; typedef T second_argument_type; typedef bool result_type; };
5.operator() returns x < y.
template <class T> struct greater_equal { bool operator()(const T& x, const T& y) const; typedef T first_argument_type; typedef T second_argument_type; typedef bool result_type; };
6.operator() returns x >= y.
template <class T> struct less_equal { bool operator()(const T& x, const T& y) const; typedef T first_argument_type; typedef T second_argument_type; typedef bool result_type; };
7.operator() returns x <= y.
8.对于模板greater,less,greater_equal,less_equal的任何指针类型特化产生全序,即使内置运算符<, >, <= ,>=不这样.
(For templates greater, less, greater_equal, and less_equal, the specializations for any pointer type yield a total order, even if the built-in operators <, >, <=, >= do not.)
20.8.6 Logical operations
1.该库为语言中的所有逻辑运算符提供了基本的函数对象类.
template <class T> struct logical_and { bool operator()(const T& x, const T& y) const; typedef T first_argument_type; typedef T second_argument_type; typedef bool result_type; };
2.operator() returns x && y.
template <class T> struct logical_or { bool operator()(const T& x, const T& y) const; typedef T first_argument_type; typedef T second_argument_type; typedef bool result_type; };
3.operator() returns x || y.
template <class T> struct logical_not { bool operator()(const T& x) const; typedef T first_argument_type; typedef bool result_type; };
4.operator() returns !x.
20.8.7 Bitwise operations
1.该库为语言中的所有位运算符提供了基本的函数对象类.
template <class T> struct bit_and { T operator()(const T& x, const T& y) const; typedef T first_argument_type; typedef T second_argument_type; typedef T result_type; };
2.operator() returns x & y.
template <class T> struct bit_or { T operator()(const T& x, const T& y) const; typedef T first_argument_type; typedef T second_argument_type; typedef T result_type; };
3.operator() returns x | y.
template <class T> struct bit_xor { T operator()(const T& x, const T& y) const; typedef T first_argument_type; typedef T second_argument_type; typedef T result_type; };
4.operator() returns x ^ y.
20.8.8 Negators
1.Negators not1和not2分别采用一元和二进制谓词,并返回其补码(5.3.1).
template <class Predicate> class unary_negate { public: explicit unary_negate(const Predicate& pred); bool operator()(const typename Predicate::argument_type& x) const; typedef typename Predicate::argument_type argument_type; typedef bool result_type; };
2.operator() returns !pred(x).
template <class Predicate>
unary_negate<Predicate> not1(const Predicate& pred);
3.返回值: unary_negate<Predicate>(pred).
template <class Predicate> class binary_negate { public: explicit binary_negate(const Predicate& pred); bool operator()(const typename Predicate::first_argument_type& x, const typename Predicate::second_argument_type& y) const; typedef typename Predicate::first_argument_type first_argument_type; typedef typename Predicate::second_argument_type second_argument_type; typedef bool result_type; };
4.operator() returns !pred(x,y).
template <class Predicate>
binary_negate<Predicate> not2(const Predicate& pred);
5.返回值: binary_negate<Predicate>(pred).
20.8.9 Function template bind
1.函数模板bind返回一个对象,该对象绑定一个作为参数传递给额外参数的可调用对象.
20.8.9.1 Function object binders
1.该条款描述了可调用对象绑定参数的统一机制.
20.8.9.1.1 Class template is_bind_expression
namespace std{ template<class T> struct is_bind_expression :integral_constant<bool, see below>{ }; }
1.is_bind_expression可用于检测由bind生成的函数对象. bind使用is_bind_expression来检测子表达式. Users应特化这个模板来指示将类型视为bind调用中的子表达式.
2.如果T是从bind,is_bind_expression<T>返回的类型,那么T应public继承自integral_constant<bool,true>,否则继承自integral_constant<bool,false>.
3.is_placeholder可能被用于检测标准placeholders _1, _2... . bind使用is_placeholder来检测placeholders. Users应特化这个模板来指示一个placeholder类型.
4.如果T是类型std::placeholders::_J,is_placeholder<T>应public继承自integral_constant<int, J>,否则继承自integral_constant<int, 0>.
20.8.9.1.2 Function template bind
1.如下:
FD是类型decay<F>::type,
fd是从std::forward<F>(f)构造的左值FD,
Ti是模板参数包BoundArgs的第i个类型,
TiD是类型decay<Ti>::type
ti应是函数参数包bound_args的第i个参数,
tid是std::forward<Ti>(ti)构造的左值TiD,
Uj是第j个forwarding call wrapper的UnBoundArgs&&...参数的推断类型,
uj是第j个与Uj有关的参数.
template<class F, class... BoundArgs>
unspecified bind(F&& f, BoundArgs&&... bound_args);
2.要求: is_constructible<FD, F>::value应是true. 对每个在BoundArgs中的Ti,is_constructible<TiD, Ti>::value应是true. INVOKE(fd, w1, w2, ..., wN)对一些值w1, w2, ..., wN(N == sizeof...(bound_args))来说应是合理的表达式.
3.返回值: 具有弱结果类型的forwaing call wrapper g. g(u1, u2, ..., uM)应是INVOKE(fd, v1, v2, ..., vN, result_of<FD cv (V1, V2, ..., VN)>::type),其中cv表示g的cv限定符和值和bound args v1, v2, ..., vN的类型像如下说的已确定. 当且仅当对应的FD或任何类型TiD构造时抛出异常,forwarding call wrapper的copy和move构造抛出异常.
4.Throws: 无,除非fd或tid中某个值构造时抛出异常.
5.备注: 返回类型需满足MoveConstructible的要求. 如果所有的FD和TiD满足CopyConstructible的要求,那么返回类型需满足CopyConstructible的要求. [Note: 这隐含所有的FD和TiD满足MoveConstructible. -end note]
template<class R, class F, class... BoundArgs>
unspecified bind(F&& f, BoundArgs&&... bound_args);
6.要求: is_constructible<FD, F>::value是true.对每个在BoundArgs中的Ti来说,is_constructible<TiD, Ti>::value是true. INVOKE(fd, w1, w2, ..., wN)对值w1, w2 , ..., wN(N == sizeof...(bound_args))来说应是合理的表达式.
7.返回值: 具有和R同义的嵌套类型result_type的forwarding call wrapper g. g(u1, u2, ..., uM)的作用应是INVOKE(fd, v1, v2, ..., vN, R),其中绑定参数v1, v2, ..., vN是值和类型如下确定. 当且仅当对应的FD或任何类型TiD构造时抛出异常,forwarding call wrapper的copy和move构造抛出异常.
8.Throws: 无,除非fd或tid中某个值构造时抛出异常.
9.备注: 返回类型需满足MoveConstructible的要求. 如果所有的FD和TiD满足CopyConstructible的要求,那么返回类型需满足CopyConstructible的要求. [Note: 这隐含所有的FD和TiD满足MoveConstructible. -end note]
10.bound argumentsv1, v2, ..., vN的值和相应的类型V1, V2, ..., VN取决于从bind调用派生的类型TiD和call wrapper g的cv限定符:
如果TiD是reference_wrapper<T>,参数值是tid.get(),类型Vi是T&;
如果is_bind_expression<TiD>::value是true,参数值是tid(std::forward<Uj>(uj)...),类型Vi是result_of<TiD cv (Uj...)>::type;
如果is_placeholder<TiD>::value的值j不是0,参数值是std::forward<Uj>(uj),类型Vi是Uj&&;
否则,值是tid,类型Vi是TiD cv&.
20.8.9.1.3 Placeholders
namespace std { namespace placeholders { // M is the implementation-defined number of placeholders extern unspecified _1; extern unspecified _2; . . . extern unspecified _M; } }
1.所有placeholders类型应是DefaultConstructible和CopyConstructible,并且它们的default构造函数和copy/move禁止抛出异常. placeholder类型是否是CopyAssignable,由实现定义.CopyAssignable placeholders的copy赋值运算符禁止抛出异常.
20.8.10 Function template mem_fn
template<class R, class T> unspecified mem_fn(R T::* pm); template<class R, class T, class... Args> unspecified mem_fn(R (T::* pm)(Args...)); template<class R, class T, class... Args> unspecified mem_fn(R (T::* pm)(Args...) const); template<class R, class T, class... Args> unspecified mem_fn(R (T::* pm)(Args...) volatile); template<class R, class T, class... Args> unspecified mem_fn(R (T::* pm)(Args...) const volatile); template<class R, class T, class... Args> unspecified mem_fn(R (T::* pm)(Args...) &); template<class R, class T, class... Args> unspecified mem_fn(R (T::* pm)(Args...) const &); template<class R, class T, class... Args> unspecified mem_fn(R (T::* pm)(Args...) volatile &); template<class R, class T, class... Args> unspecified mem_fn(R (T::* pm)(Args...) const volatile &); template<class R, class T, class... Args> unspecified mem_fn(R (T::* pm)(Args...) &&); template<class R, class T, class... Args> unspecified mem_fn(R (T::* pm)(Args...) const &&); template<class R, class T, class... Args> unspecified mem_fn(R (T::* pm)(Args...) volatile &&); template<class R, class T, class... Args> unspecified mem_fn(R (T::* pm)(Args...) const volatile &&);
1.返回值: 简单的call wrapper Fn,表达式fn(t, a2, ..., aN)等价于INVOKE(pm, t, a2, ..., aN). 当pm是指向成员函数的指针时,fn有和返回类型pm同义的嵌套类型result_type.
2.简单的call wrapper定义2个嵌套的类型,argument_type 和 result_type分别作为cv T*和Ret的同义, 当pm是指向具有cv限定符且无参数的成员函数的指针时,Ret是pm的返回类型.
3.简单的call wrapper应定义3个嵌套类型first_argument_type,second_argument_type和result_type分别作为cv T*,T1和Ret的同义, 当pm是指向具有cv限定符且带有1个类型T1的参数的成员函数的指针时,Ret是pm的返回类型.
4.Throws: 无.
20.8.11 Polymorphic function wrappers
1.此条款描述了封装任意可调用对象的多态wrapper类.
20.8.11.1 Class bad_function_call
1.当function wrapper不含目标时,bad_function_call异常会被function::operator()抛出.
namespace std{ class bad_function_call : public std::exception{ public: // 20.8.11.1.1,constructor: bad_function_call() noexcept; }; }
20.8.11.1.1 bad_function_call constructor
bad_function_call() noexcept;
1.作用: 构造bad_function_call对象.
20.8.11.2 Class template function
namespace std { template<class> class function; // undefined template<class R, class... ArgTypes> class function<R(ArgTypes...)> { public: typedef R result_type; typedef T1 argument_type; // if sizeof...(ArgTypes) == 1 and // the type in ArgTypes is T1 typedef T1 first_argument_type; // iff sizeof...(ArgTypes) == 2 and // ArgTypes contains T1 and T2 typedef T2 second_argument_type; // iff sizeof...(ArgTypes) == 2 and // ArgTypes contains T1 and T2 // 20.8.11.2.1, construct/copy/destroy: function() noexcept; function(nullptr_t) noexcept; function(const function&); function(function&&); template<class F> function(F); template<class A> function(allocator_arg_t, const A&) noexcept; template<class A> function(allocator_arg_t, const A&, nullptr_t) noexcept; template<class A> function(allocator_arg_t, const A&, const function&); template<class A> function(allocator_arg_t, const A&, function&&); template<class F, class A> function(allocator_arg_t, const A&, F); function& operator=(const function&); function& operator=(function&&); function& operator=(nullptr_t); template<class F> function& operator=(F&&); template<class F> function& operator=(reference_wrapper<F>) noexcept; ~function(); // 20.8.11.2.2, function modifiers: void swap(function&) noexcept; template<class F, class A> void assign(F&&, const A&); // 20.8.11.2.3, function capacity: explicit operator bool() const noexcept; // 20.8.11.2.4, function invocation: R operator()(ArgTypes...) const; // 20.8.11.2.5, function target access: const std::type_info& target_type() const noexcept; template <typename T> T* target() noexcept; template <typename T> const T* target() const noexcept; }; // 20.8.11.2.6, Null pointer comparisons: template <class R, class... ArgTypes> bool operator==(const function<R(ArgTypes...)>&, nullptr_t) noexcept; template <class R, class... ArgTypes> bool operator==(nullptr_t, const function<R(ArgTypes...)>&) noexcept; template <class R, class... ArgTypes> bool operator!=(const function<R(ArgTypes...)>&, nullptr_t) noexcept; template <class R, class... ArgTypes> bool operator!=(nullptr_t, const function<R(ArgTypes...)>&) noexcept; // 20.8.11.2.7, specialized algorithms: template <class R, class... ArgTypes> void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&); template<class R, class... ArgTypes, class Alloc> struct uses_allocator<function<R(ArgTypes...)>, Alloc> : true_type { }; }
1.类模板function提供了广义函数指针的多态wrapper. wrappers可以store,copy和调用任意可调用对象,该对象给定了调用签名,允许函数称为first-class对象.
2.如果表达式INVOKE(f,declval<ArgTypes>()..., R)被视为未计算的操作符,则参数类型是ArgTypes且返回类型是R的可调用对象f是可调用的.
3.类模板function是可调用对象,它的调用签名是R(ArgTypes...).
20.8.11.2.1 function construcct/copy/destroy
1.当任一拥有allocator_arg_t为第一参数的function构造函数被调用,第二参数的类型必须符合Allocator的要求. allocator参数的copy在必要时为构造函数对象的内部数据结构分配内存.
function() noexcept;
template <class A> function(allocator_arg_t, const A& a) noexcept;
2.后置条件: !*this.
function(nullptr_t) noexcept;
template <class A> function(allocator_arg_t, const A& a, nullptr_t) noexcept;
3.后置条件: !*this.
function(const function& f);
template <class A> function(allocator_arg_t, const A& a, const function& f);
4.后置条件: 如果!f成立,!*this;否则,*this指向(target)f.target()的copy.
5.Throws: 如果f的target是通过reference_wrapper或函数指针传递的可调用对象,则不应抛出异常. 否则,可能会抛出bad_alloc或存储的可调用对象的副本构造函数抛出的任何异常. [Note: 鼓励实现避免在小型可调用对象上使用动态分配的内存,例如,其中f的target是仅包含指针或对象引用和成员函数指针的对象.(注:小对象优化) -end note]
function(function&& f);
template <class A> function(allocator_arg_t, const A& a, function&& f);
6.作用: 如果!f,this无target;否则,将f移动到 this,使f成为未指定的有效状态.
template<class F> function(F f);
template <class F, class A> function(allocator_arg_t, const A& a, F f);
7.要求: F应CopyConstructible. 对于参数类型ArgTypes和返回类型R,f应可调用. A的copy和析构禁止抛出异常.
8.后置条件: 如果满足以下之一,!*this:
f是NULL函数指针.
f是NULL指向成员.
f是类模板function实例并且!f.
9.否则,this指向通过std::move(f)初始化的f的一个copy. [Note: 鼓励实现避免在小型可调用对象上使用动态分配的内存,例如,其中f的目标是仅包含指针或对象引用和成员函数指针的对象. -end note*]
10.Throws: 当f是函数指针或某个类型T的reference_wrapper<T>时,禁止抛出异常. 否则,应抛出bad_alloc或F的copy/move构造抛出的异常.
function& operator=(const function& f);
11.作用: function(f).swap(*this).
12.返回值: *this.
function& operator=(function&& f);
13.影响: 用f的target替换*this的target.
14.返回值: *this.
function& operator=(nullptr_t);
15.作用: 如果*this!=NULL,析构this的target.
16.后置条件: !(*this).
17.返回值: *this.
template<class F> function& operator=(F&& f);
18.作用: function(std::forward<F>(f)).swap(*this).
19.返回值: *this.
~function();
22.作用: 如果*this!=NULL,析构this的target.
20.8.11.2.2 function modifiers
void swap(function& other) noexcept;
1.作用: 交换*this和other的target.
template<class F, class A>
void assign(F&& f, const A& a);
2.作用: function(allocator_arg, a, std::forward<F>(f).swap(*this)).
20.8.11.2.3 function capacity
explicit operator bool() const noexcept;
1.返回值: 如果*this有target,true;否则false。
20.8.11.2.4 function invocation
R operator()(ArgTypes... args) const
1.影响: INVOKE(f, std::forward<ArgTypes>(args)..., R),其中f是*this的target对象。
2.返回值: 如果R是void,无;否则INVOKE(f, std::forward<ArgTypes>(args)..., R)的返回值.
3.Throws: 如果!*this,bad_function_call;否则,抛出被包装的可调用对象。
20.8.11.2.5 function target access
const std::type_info& target_type() const noexcept;
1.返回值: 如果*this有T类型的target,typeid(T);否则,typeid(void)。
template<typename T> T* target() noexcept;
template<typename T> const T* target() const noexcept;
2.要求: T应是一个ArgTypes和R可调用的类型。
3.返回值: 如果target_type() == typeid(T),指向存储的函数target的指针;否则,空指针。
20.8.11.2.6 null pointer comparison operators
template <class R, class... ArgTypes>
bool operator==(const function<R(ArgTypes...)>& f, nullptr_t) noexcept;
template <class R, class... ArgTypes>
bool operator==(nullptr_t, const function<R(ArgTypes...)>& f) noexcept;
1.返回值: !f.
template <class R, class... ArgTypes>
bool operator!=(const function<R(ArgTypes...)>& f, nullptr_t) noexcept;
template <class R, class... ArgTypes>
bool operator!=(nullptr_t, const function<R(ArgTypes...)>& f) noexcept;
2.返回值: (bool)f.
20.8.11.2.7 specialized algorithms
template<class R, class... ArgTypes>
void swap(function<R(ArgTypes...)>& f1, function<R(ArgTypes...)>& f2);
1.作用: f1.swap(f2).
20.8.12 Class template hash
1.23.5中定义的unordered关联容器使用类模板hash的特化作为默认hash函数。对所有对象类型Key,其拥有特化的hash<Key>,实例化的hash<Key>应:
- 满足Hash要求(17.6.3.4),其中Key作为函数调用参数类型;DefaultConstructible要求;CopyAssignable要求,
- 左值是可交换的,
- 提供2个嵌套类型result_type 和 argument_type,其分别与size_t 和 Key同义,
- 满足 如果k1 == k2是true,h(k1) == h(k2)同样是true的要求,其中h是hash<Key\>的对象且k1和k2是Key的对象。
- 满足 表达式h(k),其中h是hash<Key\>的对象,k是Key的对象,禁止抛出异常,除非hash<Key\>是用户定义的特化,它至少依赖一个用户定义的类型。
template <> struct hash<bool>;
template <> struct hash<char>;
template <> struct hash<signed char>;
template <> struct hash<unsigned char>;
template <> struct hash<char16_t>;
template <> struct hash<char32_t>;
template <> struct hash<wchar_t>;
template <> struct hash<short>;
template <> struct hash<unsigned short>;
template <> struct hash<int>;
template <> struct hash<unsigned int>;
template <> struct hash<long>;
template <> struct hash<unsigned long>;
template <> struct hash<long long>;
template <> struct hash<unsigned long long>;
template <> struct hash<float>;
template <> struct hash<double>;
template <> struct hash<long double>;
template <class T> struct hash<T*>;
2.要求: 模板特化需要满足类模板hash的要求(20.8.12)。
20.9 Metaprogramming and type traits
本小节描述了C++程序(尤其是模板)使用的组件,以支持尽可能广泛的类型,优化模板代码使用,检测与类型相关的用户错误以及在编译时执行类型推断和转换。它包括类型分类特征,类型属性检查特征和类型转换。类型分类特征描述了所有可能的C++类型的完整分类法,并声明了给定类型所属的分类法。类型属性检查特征允许检查类型或类型组合的重要特征。类型转换允许对类型的某些属性进行操作。
20.9.1 Requirements
1.UnaryTypeTrait描述类型的属性。它应该是一个类模板,它带有一个模板类型参数,以及可选的其他有助于定义所描述属性的参数。它应该是DefaultConstructible,CopyConstructible,并且可以直接或间接地从其BaseCharacteristic公开且明确地派生,该BaseCharacteristic是模板integral_constant(20.9.3)的特殊化,其模板integral_constant的参数由所描述的特定属性的要求确定。BaseCharacteristic的成员名称不得隐藏,并且在UnaryTypeTrait中应明确可用。
2.BinaryTypeTrait描述两种类型之间的关系。它应该是一个类模板,它带有两个模板类型参数,以及可选的其他有助于定义所描述关系的参数。它应是DefaultConstructible,CopyConstructible,并且可以直接或间接地从其BaseCharacteristic派生,该BaseCharacteristic是模板templateintegral_constant(20.9.3)的一种特殊形式,其参数由所描述的特定关系的需求确定。BaseCharacteristic的成员名称不得隐藏,并且在BinaryTypeTrait中应明确可用。
3.TransformationTrait修改类型的属性。它应该是一个类模板,它带有一个模板类型参数,以及(可选)其他有助于定义修改的参数。它应定义一个嵌套的名为type的类型,该类型应为已修改类型的同义词。
20.9.2 Header <type_traits> synopsis
namespace std { // 20.9.3, helper class: template <class T, T v> struct integral_constant; typedef integral_constant<bool, true> true_type; typedef integral_constant<bool, false> false_type; // 20.9.4.1, primary type categories: template <class T> struct is_void; template <class T> struct is_integral; template <class T> struct is_floating_point; template <class T> struct is_array; template <class T> struct is_pointer; template <class T> struct is_lvalue_reference; template <class T> struct is_rvalue_reference; template <class T> struct is_member_object_pointer; template <class T> struct is_member_function_pointer; template <class T> struct is_enum; template <class T> struct is_union; template <class T> struct is_class; template <class T> struct is_function; // 20.9.4.2, composite type categories: template <class T> struct is_reference; template <class T> struct is_arithmetic; template <class T> struct is_fundamental; template <class T> struct is_object; template <class T> struct is_scalar; template <class T> struct is_compound; template <class T> struct is_member_pointer; // 20.9.4.3, type properties: template <class T> struct is_const; template <class T> struct is_volatile; template <class T> struct is_trivial; template <class T> struct is_trivially_copyable; template <class T> struct is_standard_layout; template <class T> struct is_pod; template <class T> struct is_literal_type; template <class T> struct is_empty; template <class T> struct is_polymorphic; template <class T> struct is_abstract; template <class T> struct is_signed; template <class T> struct is_unsigned; template <class T, class... Args> struct is_constructible; template <class T> struct is_default_constructible; template <class T> struct is_copy_constructible; template <class T> struct is_move_constructible; template <class T, class U> struct is_assignable; template <class T> struct is_copy_assignable; template <class T> struct is_move_assignable; template <class T> struct is_destructible; template <class T, class... Args> struct is_trivially_constructible; template <class T> struct is_trivially_default_constructible; template <class T> struct is_trivially_copy_constructible; template <class T> struct is_trivially_move_constructible; template <class T, class U> struct is_trivially_assignable; template <class T> struct is_trivially_copy_assignable; template <class T> struct is_trivially_move_assignable; template <class T> struct is_trivially_destructible; template <class T, class... Args> struct is_nothrow_constructible; template <class T> struct is_nothrow_default_constructible; template <class T> struct is_nothrow_copy_constructible; template <class T> struct is_nothrow_move_constructible; template <class T, class U> struct is_nothrow_assignable; template <class T> struct is_nothrow_copy_assignable; template <class T> struct is_nothrow_move_assignable; template <class T> struct is_nothrow_destructible; template <class T> struct has_virtual_destructor; // 20.9.5, type property queries: template <class T> struct alignment_of; template <class T> struct rank; template <class T, unsigned I = 0> struct extent; // 20.9.6, type relations: template <class T, class U> struct is_same; template <class Base, class Derived> struct is_base_of; template <class From, class To> struct is_convertible; // 20.9.7.1, const-volatile modifications: template <class T> struct remove_const; template <class T> struct remove_volatile; template <class T> struct remove_cv; template <class T> struct add_const; template <class T> struct add_volatile; template <class T> struct add_cv; // 20.9.7.2, reference modifications: template <class T> struct remove_reference; template <class T> struct add_lvalue_reference; template <class T> struct add_rvalue_reference; // 20.9.7.3, sign modifications: template <class T> struct make_signed; template <class T> struct make_unsigned; // 20.9.7.4, array modifications: template <class T> struct remove_extent; template <class T> struct remove_all_extents; // 20.9.7.5, pointer modifications: template <class T> struct remove_pointer; template <class T> struct add_pointer; // 20.9.7.6, other transformations: template <std::size_t Len, std::size_t Align> struct aligned_storage; template <class T> struct decay; template <bool, class T = void> struct enable_if; template <bool, class T, class F> struct conditional; template <class... T> struct common_type; template <class T> struct underlying_type; template <class> class result_of; // not defined template <class F, class... ArgTypes> class result_of<F(ArgTypes...)>; } // namespace std
1.为此小节中的类模板添加特化的程序行为是未定义的,除非另有说明。
20.9.3 Helper classes
namespace std { template <class T, T v> struct integral_constant { static constexpr T value = v; typedef T value_type; typedef integral_constant<T,v> type; constexpr operator value_type() { return value; } }; typedef integral_constant<bool, true> true_type; typedef integral_constant<bool, false> false_type; }
1.类模板integral_constant和它关联的typedefs true_type和false_type用作基类,以定义各种类型特征的接口。
20.9.4 Unary type traits
1.这个子条款包含可能被用于编译期查询一个类型属性的模板。
2.如果相应条件是true,这些模板中的每一个都应是具有true_type的BaseCharacteristic的UnaryTypeTrait;否则是false_type。
20.9.4.1 Primary type categories
1.主要类型类别与C++标准的3.9节中给出的描述相对应。
2.对于任何给定的类型T,将这些模板之一应用于T和cv限定的T的结果将产生相同的结果。
3.[Note: 对于任何给定的类型T,正好一个主要类型类别都有一个值成员,其值评估为true。 -end note]
Table 47 -- Primary type ategory predicates -> P605
20.9.4.2 Composite type traits
1.这些模板提供了主要类型类别的便利组件,与3.9节中给出的描述相对应。
2.对于任何给定的类型T,将这些模板之一应用于T和cv限定的T的结果将产生相同的结果。
Table 48 -- Composite type category predicates -> P605
20.9.4.3 Type properties
1.这些模板提供了对类型的某些更重要属性的访问。
2.此库是否定义这些模板的任何一个的全特化或者偏特化是未定义的。
3.对于此条款中所有类模板X,当且仅当X的语义要求参数是完整类型时,用一个类模板特化作为模板参数来实例化的那个模板可能导致模板参数的隐式实例化。
Table 49 -- Type property predicates -> 606
4.[Example:
is_const<const volatile int>::value // true is_const<const int*>::value // false is_const<const int&>::value // false is_const<int[3]>::value // false is_const<const int[3]>::value // true
-end example]
5.[Example:
remove_const<const volatile int>::type // volatile int remove_const<const int* const>::type // const int* remove_const<const int&>::type // const int& remove_const<const int[3]>::type // int[3]
-end example]
6.给定以下函数原型:
template<class T>
typename add_rvalue_reference<T>::type creaate();
当且仅当下列变量定义对于某些虚拟变量t是well-formed,模板特化is_constructible<T, Args...>的谓词条件才满足:
`T t(create<Args>()...);`
[Note: 这些标记永远不会被解释为函数声明。 -end note] 就像在与T和任何Arg不相关的上下文中一样,执行访问检查。仅考虑变量初始化的即时上下文的有效性。[Note: 初始化的评估可能会导致实例化类模板专业化和功能模板特化的作用,隐式定义函数的生成等。此类副作用不在“即时范围内”并可能导致ill-formed。 -end note]
20.9.5 Type property queries
1.该副小节包含可能用于编译期查询类型属性的模板。
Table 50 - Type property queries
template <class T> struct alignment_of;
alignof(T). 要求: alignof(T)是合理的表达式
template <class T> struct rank;
如果T是数组类型,返回对应的代表T维度的整型值,否则是0。
template <class T, unsigned I = 0> struct extent;
如果T不是数组类型,或如果它的rank小于等于I,或如果I为0,且T的类型为“U的未知边界数组”,返回0。除此以外,返回T的第I个维度的边界,其中I的下标为从零开始。
2.[Example:
// the following assertions hold:
assert(rank<int>::value == 0);
assert(rank<int[2]>::value == 1);
assert(rank<int[][4]>::value == 2);
-end example]
3.[Example:
// the following assertions hold:
assert(extent<int>::value == 0);
assert(extent<int[2]>::value == 2);
assert(extent<int[2][4]>::value == 2);
assert(extent<int[][4]>::value == 0);
assert((extent<int, 1>::value) == 0);
assert((extent<int[2], 1>::value) == 0);
assert((extent<int[2][4], 1>::value) == 4);
assert((extent<int[][4], 1>::value) == 4);
-end example]
20.9.6 Relationships between types
1.本小节包含可用于在编译时查询类型之间的关系的模板。
2.这些模板中的每一个都应为BinaryTypeTrait,且BaseCharacteristic为true_type。对应条件为true,否则为false_type。
Table 51 - Type relationship predicates
3.[Example:
struct B {};
struct B1 : B {};
struct B2 : B {};
struct D : private B1, private B2 {};
is_base_of<B, D>::value // true
is_base_of<const B, D>::value // true
is_base_of<B, const D>::value // true
is_base_of<B, const B>::value // true
is_base_of<D, B>::value // false
is_base_of<B&, D&>::value // false
is_base_of<B[3], D[3]>::value // false
is_base_of<int, int>::value // false
-end example]
4.给定以下函数原型:
template <class T>
typename add_rvalue_reference<T>::type create();
如果满足以下条件,则模板特化的谓词条件为:is_convertible<From, To> 仅在以下代码中的返回表达式格式正确(包括任何隐式转换)的情况下返回函数的返回类型:
To test() { return create<From>(); }
[Note: 对于引用类型,void类型,数组类型和函数类型,此要求给出了明确的结果。 -end note] 就像在与“To”和“From”无关的上下文中一样,执行访问检查。仅考虑返回语句的表达式的直接上下文的有效性(包括对返回类型的转换)。[Note: 转换的评估可能会导致一些副作用,例如类模板专业化和函数模板专业化的实例化,隐式定义的函数的生成等。这样的副作用不在“即时上下文”中,并可能导致程序ill-formed。 -end note]
20.9.7 Transformations between types
1.本小节包含可用于在编译时将类型转换为以下预定义的规则。
2.本小节的每一个模板都是TransformationTrait。
Table 52 - Const-volatile modifications
Table 53 - Reference modifications
Table 54 - Sign modifications
Table 55 - Array modifications
1.[Example:
// the following assertions hold:
assert((is_same<remove_extent<int>::type, int>::value));
assert((is_same<remove_extent<int[2]>::type, int>::value));
assert((is_same<remove_extent<int[2][3]>::type, int[3]>::value));
assert((is_same<remove_extent<int[][3]>::type, int[3]>::value));
-end example]
2.[Example:
// the following assertions hold:
assert((is_same<remove_all_extents<int>::type, int>::value));
assert((is_same<remove_all_extents<int[2]>::type, int>::value));
assert((is_same<remove_all_extents<int[2][3]>::type, int>::value));
assert((is_same<remove_all_extents<int[][3]>::type, int>::value));
-end example]
Table 56 - Pointer modifications
Table 57 - Other transformations
1.[Note: 一个aligned_storage的典型实现:
template <std::size_t Len, std::size_t Alignment>
struct aligned_storage {
typedef struct {
alignas(Alignment) unsigned char __data[Len];
} type;
};
-end note]
2.由实现定义,是否支持任何扩展的对齐方式。
3.嵌套类型定义common_type::type应如下定义:
template <class ...T> struct common_type;
template <class T>
struct common_type<T> {
typedef T type;
};
template <class T, class U>
struct common_type<T, U> {
typedef decltype(true ? declval<T>() : declval<U>()) type;
};
template <class T, class U, class... V>
struct common_type<T, U, V...> {
typedef typename common_type<typename common_type<T, U>::type, V...>::type type;
};
4.[Example:
typedef bool (&PF1)();
typedef short (*PF2)(long);
struct S {
operator PF2() const;
double operator()(char, int&);
void fn(long) const; char data;
};
typedef void (S::*PMF)(long) const;
typedef char S::*PMD;
下列断言成立:static_assert(is_same<result_of<S(int)>::type, short>::value, "Error!");
static_assert(is_same<result_of<S&(unsigned char, int&)>::type, double>::value, "Error!");
static_assert(is_same<result_of<PF1()>::type, bool>::value, "Error!");
static_assert(is_same<result_of<PMF(unique_ptr<S>, int)>::type, void>::value, "Error!");
static_assert(is_same<result_of<PMD(S)>::type, char&&>::value, "Error!");
static_assert(is_same<result_of<PMD(const S*)>::type, const char&>::value, "Error!");
-end example]
20.10 Compile-time rational arithmetic
20.10.1 In general
1.该副小节描述ratio库。它提供类模板ratio,ratio用分子和分母精确表示任何有限有理数,该比例由类型intmax_t的编译期常量表示。
2.整个副小节,如果模板实参类型R1和R2不是ratio的特化,程序ill-formed.
20.10.2 Header <ratio> synopsis
namespace std {
// 20.10.3, class template ratio
template <intmax_t N, intmax_t D = 1> class ratio;
// 20.10.4, ratio arithmetic
template <class R1, class R2> using ratio_add = see below;
template <class R1, class R2> using ratio_subtract = see below;
template <class R1, class R2> using ratio_multiply = see below;
template <class R1, class R2> using ratio_divide = see below;
// 20.10.5, ratio comparison
template <class R1, class R2> struct ratio_equal;
template <class R1, class R2> struct ratio_not_equal;
template <class R1, class R2> struct ratio_less;
template <class R1, class R2> struct ratio_less_equal;
template <class R1, class R2> struct ratio_greater;
template <class R1, class R2> struct ratio_greater_equal;
// 20.10.6, convenience SI typedefs
typedef ratio<1, 1000000000000000000000000> yocto; // see below
typedef ratio<1, 1000000000000000000000> zepto; // see below
typedef ratio<1, 1000000000000000000> atto;
typedef ratio<1, 1000000000000000> femto;
typedef ratio<1, 1000000000000> pico;
typedef ratio<1, 1000000000> nano;
typedef ratio<1, 1000000> micro;
typedef ratio<1, 1000> milli;
typedef ratio<1, 100> centi;
typedef ratio<1, 10> deci;
typedef ratio< 10, 1> deca;
typedef ratio< 100, 1> hecto;
typedef ratio< 1000, 1> kilo;
typedef ratio< 1000000, 1> mega;
typedef ratio< 1000000000, 1> giga;
typedef ratio< 1000000000000, 1> tera;
typedef ratio< 1000000000000000, 1> peta;
typedef ratio< 1000000000000000000, 1> exa;
typedef ratio< 1000000000000000000000, 1> zetta; // see below
typedef ratio<1000000000000000000000000, 1> yotta; // see below
}
20.10.3 Class template ratio
namespace std {
template <intmax_t N, intmax_t D = 1>
class ratio {
public:
typedef ratio<num, den> type;
static constexpr intmax_t num;
static constexpr intmax_t den;
};
}
1.如果模板实参D是0或类型intmax_t不能表示模板实参N和D之一的绝对值,程序ill-formed。[Note: 这些规则确保了避免无限比率,并且对于任何负输入,其绝对值都存在一个可表示为正的值。在二进制补码表示中,这排除了最大的负值。 -end note]
2.静态数据成员num和den符合下列值,其中gcd代表N和D的绝对值的最大公约数。
num = sign(N) sign(D) abs(N) / gcd.
den = abs(D) / gcd.
20.10.4 Arithmetic on ratios
1.别名模板ratio_ass,ratio_subtract,ratio_multiply,ratio_divide中的每一个都表示对两个比率R1和R2进行算数运算的结果。如Table58所示,计算X和Y(在没有算术溢出的情况下),每个别名表示ratio<U,V>,其中U与ratio<X,Y>::num相同,V与ratio<X,Y>::den相同。
2.如果不能用intmax_t表示U或V,程序ill-formed。否则,实现应产生正确的U和V的值。如果不能用intmax_t表示X或Y,程序ill-formed,除非实现产生U和V正确的值。
Table 58 - Expressions used to perform ratio arithmetic
3.[Example:
static_assert(ratio_add<ratio<1,3>, ratio<1,6>>::num == 1, "1/3+1/6 == 1/2");
static_assert(ratio_add<ratio<1,3>, ratio<1,6>>::den == 2, "1/3+1/6 == 1/2");
static_assert(ratio_multiply<ratio<1,3>, ratio<3,2>>::num == 1, "1/3*3/2 == 1/2");
static_assert(ratio_multiply<ratio<1,3>, ratio<3,2>>::den == 2, "1/3*3/2 == 1/2");
// The following cases may cause the program to be ill-formed under some implementations
static_assert(ratio_add<ratio<1,INT_MAX>, ratio<1,INT_MAX>>::num == 2,
"1/MAX+1/MAX == 2/MAX");
static_assert(ratio_add<ratio<1,INT_MAX>, ratio<1,INT_MAX>>::den == INT_MAX,
"1/MAX+1/MAX == 2/MAX");
static_assert(ratio_multiply<ratio<1,INT_MAX>, ratio<INT_MAX,2>>::num == 1,
"1/MAX * MAX/2 == 1/2");
static_assert(ratio_multiply<ratio<1,INT_MAX>, ratio<INT_MAX,2>>::den == 2,
"1/MAX * MAX/2 == 1/2");
-end example]
20.10.5 Comparison of ratios
template <class R1, class R2>
struct ratio_equal : integral_constant<bool, see below> { };
1.如果R1::num == R2::num且R1::den == R2::den,ratio_equal<R1,R2>应派生自integral_constant<bool,true>;否则,应派生自integral_constant<bool,false>。
template <class R1, class R2>
struct ratio_not_equal : integral_constant<bool, !ratio_equal<R1, R2>::value> { };
template <class R1, class R2>
struct ratio_less : integral_constant<bool, see below> { };
2.如果R1::num R2::den < R2::num R1::den,ratio_less<R1,R2>应派生自integral_constant<bool,true>;否则,应派生自integral_constant<bool,false>。实现可能为了避免溢出使用其他算法计算。如果产生溢出,程序ill-formed。
template <class R1, class R2> struct ratio_less_equal
: integral_constant<bool, !ratio_less<R2, R1>::value> { };
template <class R1, class R2> struct ratio_greater
: integral_constant<bool, ratio_less<R2, R1>::value> { };
template <class R1, class R2> struct ratio_greater_equal
: integral_constant<bool, !ratio_less<R1, R2>::value> { };
20.10.6 SI types of ratio
1.对于每个类型定义yocto,zepto,zetta和yotta,如果在其规范中使用的两个常量都可以用intmax_t表示,则应定义typedef;如果任何一个常量都不能用intmax_t表示,则不应定义typedef。
20.11 Time utilities
20.11.1 In general
1.该副小节描述提供实用时间工具的时间库和大量C函数。
20.11.2 Header <chrono> synopsis
namespace std {
namespace chrono {
// 20.11.5, class template duration
template <class Rep, class Period = ratio<1> > class duration;
// 20.11.6, class template time_point
template <class Clock, class Duration = typename Clock::duration> class time_point;
} // namespace chrono
// 20.11.4.3 common_type specializations
template <class Rep1, class Period1, class Rep2, class Period2>
struct common_type<chrono::duration<Rep1, Period1>, chrono::duration<Rep2, Period2>>;
template <class Clock, class Duration1, class Duration2>
struct common_type<chrono::time_point<Clock, Duration1>, chrono::time_point<Clock, Duration2>>;
namespace chrono {
// 20.11.4, customization traits
template <class Rep> struct treat_as_floating_point; template <class Rep> struct duration_values;
// 20.11.5.5, duration arithmetic
template <class Rep1, class Period1, class Rep2, class Period2>
typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type
constexpr operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
template <class Rep1, class Period1, class Rep2, class Period2>
typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type
constexpr operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
template <class Rep1, class Period, class Rep2>
duration<typename common_type<Rep1, Rep2>::type, Period>
constexpr operator*(const duration<Rep1, Period>& d, const Rep2& s);
template <class Rep1, class Rep2, class Period>
duration<typename common_type<Rep1, Rep2>::type, Period>
constexpr operator*(const Rep1& s, const duration<Rep2, Period>& d);
template <class Rep1, class Period, class Rep2>
duration<typename common_type<Rep1, Rep2>::type, Period>
constexpr operator/(const duration<Rep1, Period>& d, const Rep2& s);
template <class Rep1, class Period1, class Rep2, class Period2>
typename common_type<Rep1, Rep2>::type
constexpr operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
template <class Rep1, class Period, class Rep2>
duration<typename common_type<Rep1, Rep2>::type, Period>
constexpr operator%(const duration<Rep1, Period>& d, const Rep2& s);
template <class Rep1, class Period1, class Rep2, class Period2>
typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type
constexpr operator%(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
// 20.11.5.6, duration comparisons
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator==(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator!=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator< (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator<=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator> (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
// 20.11.5.7, duration_cast
template <class ToDuration, class Rep, class Period>
constexpr ToDuration duration_cast(const duration<Rep, Period>& d);
// convenience typedefs
typedef duration<signed integer type of at least 64 bits, nano> nanoseconds;
typedef duration<signed integer type of at least 55 bits, micro> microseconds;
typedef duration<signed integer type of at least 45 bits, milli> milliseconds;
typedef duration<signed integer type of at least 35 bits > seconds;
typedef duration<signed integer type of at least 29 bits, ratio< 60>> minutes;
typedef duration<signed integer type of at least 23 bits, ratio<3600>> hours;
// 20.11.6.5, time_point arithmetic
template <class Clock, class Duration1, class Rep2, class Period2>
time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2>>::type>
operator+(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs);
template <class Rep1, class Period1, class Clock, class Duration2>
time_point<Clock, typename common_type<duration<Rep1, Period1>, Duration2>::type>
operator+(const duration<Rep1, Period1>& lhs, const time_point<Clock, Duration2>& rhs);
template <class Clock, class Duration1, class Rep2, class Period2>
time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2>>::type>
operator-(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs);
template <class Clock, class Duration1, class Duration2>
typename common_type<Duration1, Duration2>::type
operator-(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
// 20.11.6.6 time_point comparisons
template <class Clock, class Duration1, class Duration2>
bool operator==(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
template <class Clock, class Duration1, class Duration2>
bool operator!=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
template <class Clock, class Duration1, class Duration2>
bool operator< (const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
template <class Clock, class Duration1, class Duration2>
bool operator<=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
template <class Clock, class Duration1, class Duration2>
bool operator> (const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
template <class Clock, class Duration1, class Duration2>
bool operator>=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
// 20.11.6.7, time_point_cast
template <class ToDuration, class Clock, class Duration>
time_point<Clock, ToDuration> time_point_cast(const time_point<Clock, Duration>& t);
// 20.11.7, clocks
class system_clock;
class steady_clock;
class high_resolution_clock;
} // namespace chrono
} // namespace std
20.11.3 Clock requirements
1.时钟是一个由duration,time_point和一个函数now()组成的bundle,用于获取当前time_point。时钟的time_point的来源称为时钟的epoch。时钟应满足Table 59的要求。
2.在Table 59中,C1和C2表示时钟类型。t1和t2是C1::now()返回的值,其中返回t1的调用发生在返回t2的调用之前,并且这两个调用都发生在C1::time_point::max()之前。[Note: 这意味着C1不在t1和t2之间wrap around。-end note]
3.[Note: 给定时钟报告的duration与SI定义之间的duration相对差异是衡量实现质量的指标。-end note]
4.类型TC满足TrivialClock要求,如果:
TC满足Clock要求,
TC::rep,TC::duration和TC::time_point类型满足EqualityComparable(表17),LessThanComparable(表18),DefaultConstructible(表19),CopyConstructible(表21),CopyAssignable(表23),Destructible(表24)和数字类型要求(26.2)。[Note: 这尤其意味着这些类型的操作不会引发异常。 -end note]
TC::rep,TC::duration和TC::time_point类型的左值是可交换的(17.6.3.2),
TC::now()不抛出异常,
TC::time_point::clock递归地满足TrivialClock的要求。
20.11.4 Time-related traits
20.11.4.1 treat_as_floating_point
template <class Rep> struct treat_as_floating_point
: is_floating_point<Rep> { };
1.duration模板使用treat_as_floating_point属性来确认是否duration对象可以转换为另一个带有不同计次周期的duration。如果treat_as_floating_point<Rep>::value是true,那么大多数durations间允许隐式转换。否则,隐式转换依赖它们的tick periods。
[Note: 这个属性的动机是为指明是否一个给定的类表现得像floating-point类型,从而允许在可接受的精度损失下将一个值除以另一个。如果treat_as_floating_point<Rep>::value为false,则出于这些转换的目的,Rep将被视为表现为整数类型。 -end note]
20.11.4.2 duration_values
template <class Rep>
struct duration_values {
public:
static constexpr Rep zero();
static constexpr Rep min();
static constexpr Rep max();
};
1.duration模板使用duration_values特征来构造duration表示形式(Rep)的特殊值。这样做是因为表示形式可能是具有行为的类类型,而这种行为需要其他一些实现才能返回这些特殊值。在这种情况下,该类类型的作者应专门指定duration_values以返回指示的值。
static constexpr Rep zero();
2.返回值: Rep(0)。
[Note: 使用Rep(0)而不是Rep()是因为Rep()可能有一些其他的意义,比如未初始化的值。 -end note]
3.备注: The value returned shall be the additive identity.
static constexpr Rep min();
4.返回值: numeric_limits<Rep>::lowest()。
5.备注: 返回值应小于等于zero()。
static constexpr Rep max();
6.返回值: numeric_limits<Rep>::max()。
7.备注: 返回值应大于zero()。
20.11.4.3 Specializations of common_type
template <class Rep1, class Period1, class Rep2, class Period2>
struct common_type<chrono::duration<Rep1, Period1>, chrono::duration<Rep2, Period2>> {
typedef chrono::duration<typename common_type<Rep1, Rep2>::type, see below> type;
};
1.common_type此特化指明duration的持续时间应Period1和Period2的最大公约数。
[Note: 这可以通过 Period1::num和Period2::num的最大公约数和Period1::den和Period2::den的最小公倍数 之比 计算出。 -end note]
2.[Note: typedef name类型是具有最大范围的duration,其中两个period的参数都将转换为该duration,不需要除法运算。尽管float duration可能会产生舍入误差,但这种类型的表示形式应能够保留此转换产生的任何值而不会出现截断错误。-end note]
template <class Clock, class Duration1, class Duration2>
struct common_type<chrono::time_point<Clock, Duration1>, chrono::time_point<Clock, Duration2>> {
typedef chrono::time_point<Clock, typename common_type<Duration1, Duration2>::type> type;
};
3.两种time_point类型的常见类型是与两种类型具有相同时钟且两种持续时间的常见类型的time_point。
20.11.5 Class template duration
1.duration类型用于测量两个时间点(time_points)之间的时间。duration的表现形式包含计次数和计次周期。其中计次周期是一个编译期有理数常量,表示从一个计次到下一个的秒数。使用模板ratio的有理数常量表示。
template <class Rep, class Period = ratio<1>>
class duration {
public:
typedef Rep rep;
typedef Period period;
private:
rep rep_; // exposition only
public:
// 20.11.5.1, construct/copy/destroy:
constexpr duration() = default;
template <class Rep2>
constexpr explicit duration(const Rep2& r);
template <class Rep2, class Period2>
constexpr duration(const duration<Rep2, Period2>& d);
~duration() = default;
duration(const duration&) = default;
duration& operator=(const duration&) = default;
// 20.11.5.2, observer:
constexpr rep count() const;
// 20.11.5.3, arithmetic:
constexpr duration operator+() const;
constexpr duration operator-() const;
duration& operator++();
duration operator++(int);
duration& operator--();
duration operator--(int);
duration& operator+=(const duration& d);
duration& operator-=(const duration& d);
duration& operator*=(const rep& rhs);
duration& operator/=(const rep& rhs);
duration& operator%=(const rep& rhs);
duration& operator%=(const duration& rhs);
// 20.11.5.4, special values:
static constexpr duration zero();
static constexpr duration min();
static constexpr duration max(); };
2.要求: Rep应是算术类型或一个模拟算术类型的类。
3.备注: 如果使用模板参数Rep的duration类型实例化duration,程序ill-formed。
4.备注: 如果Period不是ratio的特化,程序ill-formed。
5.备注: 如果Period::num不是正数,程序ill-formed。
6.要求: duration的成员禁止抛出异常,除非... ( Members of duration shall not throw exceptions other than those thrown by the indicated operations on their representations.)
[Example:
duration<long, ratio<60>> d0; // holds a count of minutes using a long
duration<long long, milli> d1; // holds a count of milliseconds using a long long
duration<double, ratio<1, 30>> d2; // holds a count with a tick period of 1/30 of a second
// (30 Hz) using a double
-end example]
20.11.5.1 duration constructors
template <class Rep2> constexpr explicit duration(const Rep2& r);
1.备注: 该构造函数禁止参与重载决议,除非Rep2可隐式转换成rep,且:
treat_as_floating_point<rep>::value为true,或
treat_as_floating_point<Rep2>::value为false。
[Example:
duration<int,milli> d(3);
duration<int,milli> d(3.5);
-end example]
2.作用: 构造duration对象。
3.后置条件: count() == static_cast<rep>(r)。
template <class Rep2, class Period2> constexpr duration(const duration<Rep2, Period2>& d);
4.备注: 这个构造函数不参与重载决议,除非tread_as_floating_point<rep>::value为true或ratio_divide<Period2, period>::den是1且treat_as_floating_point<Rep2>::value为false.
[Note: 此要求当基于整数的duration类型转换时,防止隐式截断错误。这种结构很容易导致duration的值产生歧义。 -end note]
[Example:
duration<int, milli> ms(3);
duration<int, micro> us = ms; // OK
duration<int, milli> ms2 = us; // error
-end example]
5.作用: 构造duration对象,该对象从durationcast<duration>(d).count()构造rep。
(remark: 即要么时长使用浮点计次,要么 Period2 能被周期整除)
20.11.5.2 duration observer
constexpr rep count() const;
1.返回值: rep_。
20.11.5.3 duration arithmetic
constexpr duration operator+() const;
1.返回值: *this。
constexpr duration operator-() const;
2.返回值: duration(-rep_)。
duration& operator++();
3.作用: ++rep_。
4.返回值: *this。
duration operator++(int);
5.返回值: duration(rep_++)。
duration& operator--();
6.作用: --rep_。
7.返回值: *this。
duration operator--(int);
8.返回值: duration(rep_--)。
duration& operator+=(const duration& d);
9.作用: rep_ += d.count()。
10.返回值: *this。
duration& operator-=(const duration& d);
11.作用: rep_ -= d.count()。
12.返回值: *this。
duration& operator*=(const rep& rhs);
13.作用: rep_ *= rhs。
14.返回值: *this。
duration& operator/=(const rep& rhs);
15.作用: rep_ /= rhs。
16.返回值: *this。
duration& operator%=(const rep& rhs);
17.作用: rep_ %= rhs。
18.返回值: *this。
duration& operator%=(const duration& rhs);
19.作用: rep_ %= rhs.count()。
20.返回值: *this。
20.11.5.4 duration special values
static constexpr duration zero();
1.返回值: duration(duration_valuse<rep>::zero())。
static constexpr duration min();
2.返回值: duration(duration_values<rep>::min())。
static constexpr duration max();
3.返回值: duration(duration_values<rep>::max())。
20.11.5.5 duration non-member arithmetic
1.下面的函数描述中,CD表示函数的返回值。CR(A,B)表示common_type<A, B>::type。
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
2.返回值: CD(CD(lhs).count() + CD(rhs).count())。
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
3.返回值: CD(CD(lhs).count() - CD(rhs).count())。
template <class Rep1, class Period, class Rep2>
constexpr duration<typename common_type<Rep1, Rep2>::type, Period>
operator*(const duration<Rep1, Period>& d, const Rep2& s);
4.备注: 此运算符禁止参与重载决议,除非Rep2可隐式转换为CR(Rep1, Rep2)。
5.返回值: CD(CD(d).count() * s)。
template <class Rep1, class Rep2, class Period>
constexpr duration<typename common_type<Rep1, Rep2>::type, Period>
operator*(const Rep1& s, const duration<Rep2, Period>& d);
6.备注: 此运算符禁止参与重载决议,除非Rep1可隐式转换为CR(Rep1, Rep2)。
7.返回值: d * s。
template <class Rep1, class Period, class Rep2>
constexpr duration<typename common_type<Rep1, Rep2>::type, Period>
operator/(const duration<Rep1, Period>& d, const Rep2& s);
8.备注: 此运算符禁止参与重载决议,除非Rep2可隐式转换为CR(Rep1, Rep2)且Rep2不是duration实例。
9.返回值: CD(CD(d).count() / s)。
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr typename common_type<Rep1, Rep2>::type
operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
10.返回值: CD(lhs).count() / CD(rhs).count()。
template <class Rep1, class Period, class Rep2>
constexpr duration<typename common_type<Rep1, Rep2>::type, Period>
operator%(const duration<Rep1, Period>& d, const Rep2& s);
11.备注: 此运算符禁止参与重载决议,除非Rep2可隐式转换为CR(Rep1, Rep2)且Rep2不是duration实例。
12.返回值: CD(CD(d).count() % s)。
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type
operator%(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
13.返回值: CD(CD(lhs).count() % CD(rhs).count())。
20.11.5.6 duration comparisons
1.下面的函数描述中,CT表示common_type<A, B>::type,其中A和B是函数的参数类型。
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator==(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
2.返回值: CT(lhs).count() == CT(rhs).count()。
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator!=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
3.返回值: !(lhs == rhs)。
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator<(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
4.返回值: CT(lhs).count() < CT(rhs).count()。
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator<=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
5.返回值: !(rhs < lhs)。
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator>(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
6.返回值: rhs < lhs。
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
7.返回值: !(lhs < rhs)。
20.11.5.7 duration_cast
template <class ToDuration, class Rep, class Period>
constexpr ToDuration duration_cast(const duration<Rep, Period>& d);
1.备注: 此函数禁止参与重载决议,除非ToDuration是duration实例。
2.返回值: 令 CF 为ratio_divide<Period, typename ToDuration::period>,且CR为common_type<typename ToDuration::rep, Rep, intmax_t>::type。
如果CF::num == 1且CF::den == 1,返回ToDuration(static_cast<typename ToDuration::rep>(d.count()))
否则,如果CF::num != 1且CF::den == 1,返回Toduration(static_cast<typename ToDuration::rep>(static_cast<CR>(d.count()) * static_cast<CR>(CF::num)))
否则,如果CF::num == 1且CF::den != 1,返回ToDuration(static_cast<typename ToDuration::rep>(static_cast<CR>(d.count()) / static_cast<CR>(CF::den)))
否则,返回ToDuration(static_cast<typename ToDuration::rep>(static_cast<CR>(d.count()) * static_cast<CR>(CF::num) / static_cast<CR>(CF::den)))
Notes: 此函数不使用任何隐式转换;所有转换都有static_cast完成。当在编译时知道一个或多个参数为1时,它将避免乘法和除法。Intermediate computations are carried out in the widest representation and only converted to the destination representation at the final step.
20.11.6 Class template time_point
template <class Clock, class Duration = typename Clock::duration>
class time_point {
public:
typedef Clock clock;
typedef Duration duration;
typedef typename duration::rep rep;
typedef typename duration::period period;
private:
duration d_; // exposition only
public: // 20.11.6.1, construct:
time_point(); // has value epoch
explicit time_point(const duration& d); // same as time_point() + d
template <class Duration2>
time_point(const time_point<clock, Duration2>& t);
// 20.11.6.2, observer:
duration time_since_epoch() const;
// 20.11.6.3, arithmetic:
time_point& operator+=(const duration& d);
time_point& operator-=(const duration& d);
// 20.11.6.4, special values:
static constexpr time_point min();
static constexpr time_point max();
};
1.Clock应满足Clock需求(20.11.7)。
2.如果Duration不是duration的实例,程序ill-formed。
20.11.6.1 time_point constructors
time_point();
1.作用: 构造timepoint对象,使用duration::zero()初始化d。这样的time_point对象表示 epoch(纪元)。
time_point(const duration& d);
2.作用: 构造timepoint对象,使用d初始化d。这样的time_point对象表示 epoch + d。
template <class Duration2>
time_point(const time_point<clock, Duration2>& t);
3.备注: 此构造函数禁止参与重载决议,除非Duration2可隐式转换成duration。
4.作用: 构造timepoint对象,使用t.time_since_epoch()初始化d。
20.11.6.2 time_point observer
duration time_since_epoch() const;
1.返回值: d_。
20.11.6.3 time_point arithmetic
time_point& operator+=(const duration& d);
1.作用: d_ += d。
2.返回值: *this。
time_point& operator-=(const duration& d);
3.作用: d_ -= d。
4.返回值: *this。
20.11.6.4 time_point special values
static constexpr time_point min();
1.返回值: time_point(duration::min())。
static constexpr time_point max();
2.返回值: time_point(duration::max())。
20.11.6.5 time_point non-member arithmetic
template <class Clock, class Duration1, class Rep2, class Period2>
time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2>>::type>
operator+(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs);
1.返回值: CT(lhs) += rhs,其中CT是返回值类型。
template <class Rep1, class Period1, class Clock, class Duration2>
time_point<Clock, typename common_type<duration<Rep1, Period1>, Duration2>::type>
operator+(const duration<Rep1, Period1>& lhs, const time_point<Clock, Duration2>& rhs);
2.返回值: rhs + lhs。
template <class Clock, class Duration1, class Rep2, class Period2>
time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2>>::type>
operator-(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs);
3.返回值: lhs + (-rhs)。
template <class Clock, class Duration1, class Duration2>
typename common_type<Duration1, Duration2>::type
operator-(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
4.返回值: lhs.time_since_epoch() - rhs.time_since_epoch()。
20.11.6.6 time_point comparisons
template <class Clock, class Duration1, class Duration2>
bool operator==(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
1.返回值: lhs.time_since_epoch() == rhs.time_since_epoch()。
template <class Clock, class Duration1, class Duration2>
bool operator!=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
2.返回值: !(lhs==rhs)。
template <class Clock, class Duration1, class Duration2>
bool operator<(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
3.返回值: lhs.time_since_epoch() < rhs.time_since_epoch()。
template <class Clock, class Duration1, class Duration2>
bool operator<=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
4.返回值: !(rhs < lhs)。
template <class Clock, class Duration1, class Duration2>
bool operator>(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
5.返回值: rhs < lhs。
template <class Clock, class Duration1, class Duration2>
bool operator>=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
6.返回值: !(lhs < rhs)。
20.11.6.7 time_point_cast
template <class ToDuration, class Clock, class Duration>
time_point<Clock, ToDuration> time_point_cast(const time_point<Clock, Duration>& t);
1.备注: 此函数禁止参与重载决议,除非ToDuration是duration实例。
2.返回值: time_point<Clock, ToDuration>(duration_cast<ToDuration>(t.time_since_epoch()))。
20.11.7 Clocks
1.此小节定义的类型满足TrivialClock要求(20.11.3)。
20.11.7.1 Class system_clock
1.system_clock的对象表示系统范围实时时钟的挂钟时间。
class system_clock {
public:
typedef see below rep;
typedef ratio<unspecified , unspecified > period;
typedef chrono::duration<rep, period> duration;
typedef chrono::time_point<system_clock> time_point;
static const bool is_steady = unspecified;
static time_point now() noexcept;
// Map to C API
static time_t to_time_t (const time_point& t) noexcept;
static time_point from_time_t(time_t t) noexcept;
};
typedef unspecified system_clock::rep;
2.要求: system_clock::duration::min() < system_clock::duration::zero()。
[Note: 这意味着rep是带符号的类型。 -end note]
static time_t to_time_t(const time_point& t) noexcept;
3.返回值: 当两个值都限于time_t和time_point的精度中的较粗略值时,一个time_t对象表示与t相同的时间点。由实现定义,是将值四舍五入到所需的精度。
static time_point from_time_t(time_t t) noexcept;
4.返回值: 当两个值都限制为time_t和time_point的精度中的较粗糙值时,一个time_point对象表示与t相同的时间点。由实现定义,是将值四舍五入到所需的精度。
20.11.7.2 Class steady_clock
1.stable_clock类的对象表示以下时钟:对于它们的时钟,time_point的值永远不会随着物理时间的增长而减少,并且对于它们的time_point的值相对于实时以稳定的速率增长。即,时钟可能无法调整。
class steady_clock {
public:
typedef unspecified rep;
typedef ratio<unspecified , unspecified> period;
typedef chrono::duration<rep, period> duration;
typedef chrono::time_point<unspecified, duration> time_point;
static const bool is_steady = true;
static time_point now() noexcept;
};
20.11.7.3 Class high_resolution_clock
1.高分辨率时钟类的对象以最短的计次周期表示时钟。high_resolution_clock可以是system_clock或stable_clock的同义词。
class high_resolution_clock {
public:
typedef unspecified rep;
typedef ratio<unspecified , unspecified> period;
typedef chrono::duration<rep, period> duration;
typedef chrono::time_point<unspecified , duration> time_point;
static const bool is_steady = unspecified ;
static time_point now() noexcept;
};
20.11.8 Date and time functions
1.Table 60 描述了<ctime>头文件。
2.内容与标准C库头文件<time.h>相同。函数asctime,ctime,gmtime和localtime不需要避免数据竞争(17.6.5.9)。
20.12
20.12.1 Header <scoped_allocator> synopsis
// scoped allocator adaptor
template <class OuterAlloc, class... InnerAlloc>
class scoped_allocator_adaptor;
template <class OuterA1, class OuterA2, class... InnerAllocs>
bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
template <class OuterA1, class OuterA2, class... InnerAllocs>
bool operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
1.类模板scoped_allocator_adaptor是一个allocator模板,它指定容器要使用的内存资源(外部allocator)(就像其他任何分配器一样),还指定一个内部分配器资源,该资源将传递给容器内每个元素的构造函数。该adaptor用一个外部和零个或多个内部allocator类型实例化。如果仅使用一种adaptor类型实例化,则内部allocator将成为scoped_allocator_adaptor本身,从而为容器和容器中的每个元素使用相同的分配器资源,如果元素本身是容器,则它们的每个元素都是递归的。如果使用多个adaptor实例化,则第一个allocator是容器使用的外部allocator,第二个分配器传递给容器元素的构造函数,如果元素本身是容器,则第三个allocator传递给容器元素的元素,依此类推。如果容器嵌套的深度大于allocator的数量,则对于单个剩余的递归,最后一次allocator将重复使用,就像在单allocator的情况下一样。
namespace std {
template <class OuterAlloc, class... InnerAllocs>
class scoped_allocator_adaptor : public OuterAlloc {
private:
typedef allocator_traits<OuterAlloc> OuterTraits; // exposition only
scoped_allocator_adaptor<InnerAllocs...> inner; // exposition only
public:
typedef OuterAlloc outer_allocator_type;
typedef see below inner_allocator_type;
typedef typename OuterTraits::value_type value_type;
typedef typename OuterTraits::size_type size_type;
typedef typename OuterTraits::difference_type difference_type;
typedef typename OuterTraits::pointer pointer;
typedef typename OuterTraits::const_pointer const_pointer;
typedef typename OuterTraits::void_pointer void_pointer;
typedef typename OuterTraits::const_void_pointer const_void_pointer;
typedef see below propagate_on_container_copy_assignment;
typedef see below propagate_on_container_move_assignment;
typedef see below propagate_on_container_swap;
template <class Tp> struct rebind {
typedef scoped_allocator_adaptor< OuterTraits::template rebind_alloc<Tp>, InnerAllocs...> other;
};
scoped_allocator_adaptor();
template <class OuterA2>
scoped_allocator_adaptor(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs) noexcept;
scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept;
scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept;
template <class OuterA2>
scoped_allocator_adaptor( const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other) noexcept;
template <class OuterA2>
scoped_allocator_adaptor( const scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other) noexcept;
~scoped_allocator_adaptor();
inner_allocator_type& inner_allocator() noexcept;
const inner_allocator_type& inner_allocator() const noexcept;
outer_allocator_type& outer_allocator() noexcept;
const outer_allocator_type& outer_allocator() const noexcept;
pointer allocate(size_type n);
pointer allocate(size_type n, const_void_pointer hint);
void deallocate(pointer p, size_type n);
size_type max_size() const;
template <class T, class... Args> void construct(T* p, Args&& args);
template <class T1, class T2, class... Args1, class... Args2>
void construct(pair<T1, T2>* p,
piecewise_construct_t, tuple<Args1...> x, tuple<Args2...> y);
template <class T1, class T2>
void construct(pair<T1, T2>* p);
template <class T1, class T2, class U, class V>
void construct(pair<T1, T2>* p, U&& x, V&& y);
template <class T1, class T2, class U, class V>
void construct(pair<T1, T2>* p, const pair<U, V>& x);
template <class T1, class T2, class U, class V>
void construct(pair<T1, T2>* p, pair<U, V>&& x);
template <class T> void destroy(T* p);
scoped_allocator_adaptor select_on_container_copy_construction() const;
};
template <class OuterA1, class OuterA2, class... InnerAllocs>
bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
template <class OuterA1, class OuterA2, class... InnerAllocs>
bool operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
}
20.12.2 Scoped allocator adaptor member types
typedef see below inner_allocator_type;
1.类型: 如果sizeof...(InnerAlloc)是0,scoped_allocator_adaptor<OuterAlloc>;否则,scoped_allocator_adaptor<InnerAllocs...>。
typedef see below propagate_on_container_copy_assignment;
2.类型: 如果对OuterAlloc和InnerAllocs...里每个A来说,allocator_traits<A>::propagate_on_container_copy_assignment::value是true,true_type;否则,false_type。
typedef see below propagate_on_container_move_assignment;
3.类型: 如果对OuterAlloc和InnerAllocs...里每个A来说,allocator_traits<A>::propagate_on_container_copy_assignment::value是true,true_type;否则,false_type。
typedef see below propagate_on_container_swap;
4.类型: 如果对OuterAlloc和InnerAllocas...里每个A来说allocator_traits<A>::propagate_on_container_swap::value是true,true_type;否则,false_type。
20.12.3 Scoped allocator adaptor constructors
scoped_allocator_adaptor();
1.作用: 值初始化OuterAlloc基类和内部allocator对象。
template <class OuterA2>
scoped_allocator_adaptor(OuterA2&& outerAlloc,
const InnerAllocs&... innerAllocs) noexcept;
2.要求: OuterAlloc应从OuterA2可构造。
3.作用: 用std::forward<OuterA2>(outerAlloc)初始化OuterAlloc基类,innerAllocs...初始化inner (因此在adaptor内从参数列表用对应的allocator递归初始化每个allocator)。
scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept;
4.作用: 从other用对应的allocator初始化在adaptor内的allocator。
scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept;
5.作用: 从other用对应的allocator移动构造adaptor内的每个allocator。
template <class OuterA2>
scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2,
InnerAllocs...>& other) noexcept;
6.要求: OuterAlloc应从OuterA2可构造。
7.作用: 从other中用对应的allocator初始化在adaptor内的每个allocator。
template <class OuterA2>
scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2,
InnerAllocs...>&& other) noexcept;
8.要求: OuterAlloc应从OuterA2可构造。
9.作用: 从other中用对应的右值allocator初始化在adaptor内的每个allocator。
pass.