| Document Number: | |
|---|---|
| Date: | |
| Revises: | |
| Editor: | Google, Inc. |
Note: this is an early draft. It’s known to be incomplet and incorrekt, and it has lots of bad formatting.
This technical specification describes extensions to the C++
Standard Library (
This technical specification is non-normative. Some of the library components in this technical specification may be considered for standardization in a future version of C++, but they are not currently part of any C++ standard. Some of the components in this technical specification may never be standardized, and others may be standardized in a substantially changed form.
The goal of this technical specification is to build more widespread existing practice for an expanded C++ standard library. It gives advice on extensions to those vendors who wish to provide them.
The following referenced document is indispensable for the application of this document. For dated references, only the edition cited applies. For undated references, the latest edition of the referenced document (including any amendments) applies.
ISO/IEC 14882:— is herein called the C++ Standard. References to clauses within the C++ Standard are written as "C++14 §3.2". The library described in ISO/IEC 14882:— clauses 17–30 is herein called the C++ Standard Library.
Unless otherwise specified, the whole of the C++ Standard's Library
introduction (
Since the extensions described in this technical specification
are experimental and not part of the C++ standard library, they
should not be declared directly within namespace
std.
Unless otherwise specified, all components described in this technical specification either:
::experimental::fundamentals_v2
to a namespace defined in the C++ Standard Library,
such as std or std::chrono, or
std.
std::experimental::fundamentals_v2::chrono
because the C++ Standard Library defines std::chrono.
This TS does not define std::pmr::experimental::fundamentals_v2
because the C++ Standard Library does not define std::pmr.
— end example ]
Each header described in this technical
specification shall import the contents of
std::experimental::fundamentals_v2 into
std::experimental as if by
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {}
}
}
This technical specification also describes some experimental
modifications to existing interfaces in the C++ Standard Library.
These modifications are described by quoting the affected parts of
the standard
and using underlining to represent added text and strike-through to represent deleted text.
Unless otherwise specified, references to other entities
described in this technical specification are assumed to be
qualified with std::experimental::fundamentals_v2::,
and references to entities described in the standard are assumed
to be qualified with std::.
Extensions that are expected to eventually be added to an
existing header are provided inside the
header, which shall include
the standard contents of as if by
#include
New headers are also provided in the
directory, but without such an
#include.
For the purposes of this document, the terms and definitions given in the C++ Standard and the following apply.
This section describes tentative plans for future versions of this technical specification and plans for moving content into future versions of the C++ Standard.
The C++ committee intends to release a new version of this
technical specification approximately every year, containing the
library extensions we hope to add to a near-future version of the
C++ Standard. Future versions will define their contents in
std::experimental::fundamentals_v3,
std::experimental::fundamentals_v4, etc., with the
most recent implemented version inlined into
std::experimental.
When an extension defined in this or a future version of this
technical specification represents enough existing practice, it
will be moved into the next version of the C++ Standard by
removing the experimental::fundamentals_vN
segment of its namespace and by removing the
experimental/ prefix from its header's path.
For the sake of improved portability between partial implementations of various C++ standards,
WG21 (the ISO technical committee for the C++ programming language) recommends
that implementers and programmers follow the guidelines in this section concerning feature-test macros.
Implementers who provide a new standard feature should define a
macro with the recommended name,
in the same circumstances under which the feature is available
(for example, taking into account relevant command-line options),
to indicate the presence of support for that feature.
Implementers should define that macro with the value specified in
the most recent version of this technical specification that they
have implemented.
The recommended macro name is "__cpp_lib_experimental_" followed by the string in the "Macro Name Suffix" column.
Programmers who wish to determine whether a feature is available in an implementation should base that determination on
the presence of the header (determined with __has_include()
and
the state of the macro with the recommended name.
(The absence of a tested feature may result in a program with
decreased functionality, or the relevant functionality may be provided
in a different way.
A program that strictly depends on support for a feature can just
try to use the feature unconditionally;
presumably, on an implementation lacking necessary support,
translation will fail.)
| Doc. No. | Title | Primary Section | Macro Name Suffix | Value | Header |
|---|---|---|---|---|---|
| N3915 | apply() call a function with arguments from a tuple | apply |
201402 | |
|
| N3932 | Variable Templates For Type Traits | type_trait_variable_templates |
201402 | |
|
| N3866 | Invocation type traits | invocation_type |
201406 | |
|
| P0013R1 | Logical Operator Type Traits | logical_traits |
201511 | |
|
| N4502 | The C++ Detection Idiom | detect |
201505 | |
|
| N4388 | A Proposal to Add a Const-Propagating Wrapper to the Standard Library | propagate_const
| 201505 |
| |
| N3916 | Type-erased allocator for std::function |
function_erased_allocator |
201406 | |
|
| N3905 | Extending std::search to use Additional Searching Algorithms |
boyer_moore_searching |
201411 | |
|
| N4076 | A proposal to add a generalized callable negator | not_fn
| 201406 |
| |
| N3672, N3793 | A utility class to represent optional objects | optional |
201411 | |
|
| N3804 | Any Library Proposal | any |
201411 | |
|
| N3921 | string_view: a non-owning reference to a string |
string_view |
201411 | |
|
| N3920 | Extending shared_ptr to Support Arrays | shared_ptr_arrays |
201406 | |
|
| N3916 | Polymorphic Memory Resources | memory_resources |
201402 | |
|
| N4282 | The World’s Dumbest Smart Pointer | observer_ptr
| 201411 |
| |
| N4273 | Uniform Container Erasure | erase_if |
201411 | |
|
| N4391 | make_array | make_array |
201505 | |
|
| N4257 | Delimited iterators | ostream_joiner |
201411 | |
|
| N3916 | Type-erased allocator for std::promise |
promise_erased_allocator |
201406 | |
|
| N3916 | Type-erased allocator for std::packaged_task |
packaged_task_erased_allocator |
201406 | |
|
| N3925 | A sample Proposal |
sample |
201402 | |
|
| N4061 | Greatest Common Divisor and Least Common Multiple | gcd_lcm |
201411 | |
|
| N4531 | std::rand replacement |
randint |
201511 | |
|
| N4519 | Source-Code Information Capture | source_location |
201505 | |
Implementations that conform to this technical specification shall behave as if the modifications contained in this section are made to the C++ Standard.
The following changes to the uses_allocator trait and to the description of uses-allocator construction
allow a memory_resource pointer act as an allocator in many circumstances.
20.7.7 uses_allocator [allocator.uses]
20.7.7.1 uses_allocator trait [allocator.uses.trait]
template struct uses_allocator;
- Remarks:
- Automatically detects whether
Thas a nestedallocator_typethat is convertible fromAlloc. Meets the BinaryTypeTrait requirements (C++14 §20.10.1 ). The implementation shall provide a definition that is derived fromtrue_typeif a typeT::allocator_typeexists and eitheris_convertible_vor!= false T::allocator_typeis an alias forstd::experimental::erased_type(3.1.2 ), otherwise it shall be derived fromfalse_type. A program may specialize this template to derive fromtrue_typefor a user-defined typeTthat does not have a nestedallocator_typebut nonetheless can be constructed with an allocator where either:
- the first argument of a constructor has type
allocator_arg_tand the second argument has typeAllocor- the last argument of a constructor has type
Alloc.20.7.7.2 uses-allocator construction [allocator.uses.construction]
Uses-allocator construction with allocator
Allocrefers to the construction of an objectobjof typeT, using constructor argumentsv1, v2, ..., vNof typesV1, V2, ..., VN, respectively, and an allocatorallocof typeAlloc, whereAlloceither (1) meets the requirements of an allocator (C++14 §17.6.3.5 ), or (2) is a pointer type convertible tostd::experimental::pmr::memory_resource*(8.5 ), according to the following rules:
synopsis#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
// 3.1.2, Class erased_type
struct erased_type { };
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
erased_typestruct erased_type { };
The erased_type struct is an empty struct that serves as a placeholder for a type T in situations where the actual type T is determined at runtime.
For example, the nested type, allocator_type, is an alias for erased_type in classes that use type-erased allocators (see
#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
// See C++14 §20.4.2.5 , tuple helper classes
template constexpr size_t tuple_size_v
= tuple_size::value;
// 3.2.2, Calling a function with a tuple of arguments
template
constexpr decltype(auto) apply(F&& f, Tuple&& t);
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
tuple of argumentstemplate
constexpr decltype(auto) apply(F&& f, Tuple&& t);
Given the exposition only function
template
constexpr decltype(auto) apply_impl( // exposition only
F&& f, Tuple&& t, index_sequence) {
return INVOKE(std::forward(f), std::get(std::forward(t))...);
}
Equivalent to
return apply_impl(std::forward(f), std::forward(t),
make_index_sequence>>{});
#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
// See C++14 §20.10.4.1 , primary type categories
template constexpr bool is_void_v
= is_void::value;
template constexpr bool is_null_pointer_v
= is_null_pointer::value;
template constexpr bool is_integral_v
= is_integral::value;
template constexpr bool is_floating_point_v
= is_floating_point::value;
template constexpr bool is_array_v
= is_array::value;
template constexpr bool is_pointer_v
= is_pointer::value;
template constexpr bool is_lvalue_reference_v
= is_lvalue_reference::value;
template constexpr bool is_rvalue_reference_v
= is_rvalue_reference::value;
template constexpr bool is_member_object_pointer_v
= is_member_object_pointer::value;
template constexpr bool is_member_function_pointer_v
= is_member_function_pointer::value;
template constexpr bool is_enum_v
= is_enum::value;
template constexpr bool is_union_v
= is_union::value;
template constexpr bool is_class_v
= is_class::value;
template constexpr bool is_function_v
= is_function::value;
// See C++14 §20.10.4.2 , composite type categories
template constexpr bool is_reference_v
= is_reference::value;
template constexpr bool is_arithmetic_v
= is_arithmetic::value;
template constexpr bool is_fundamental_v
= is_fundamental::value;
template constexpr bool is_object_v
= is_object::value;
template constexpr bool is_scalar_v
= is_scalar::value;
template constexpr bool is_compound_v
= is_compound::value;
template constexpr bool is_member_pointer_v
= is_member_pointer::value;
// See C++14 §20.10.4.3 , type properties
template constexpr bool is_const_v
= is_const::value;
template constexpr bool is_volatile_v
= is_volatile::value;
template constexpr bool is_trivial_v
= is_trivial::value;
template constexpr bool is_trivially_copyable_v
= is_trivially_copyable::value;
template constexpr bool is_standard_layout_v
= is_standard_layout::value;
template constexpr bool is_pod_v
= is_pod::value;
template constexpr bool is_literal_type_v
= is_literal_type::value;
template constexpr bool is_empty_v
= is_empty::value;
template constexpr bool is_polymorphic_v
= is_polymorphic::value;
template constexpr bool is_abstract_v
= is_abstract::value;
template constexpr bool is_final_v
= is_final::value;
template constexpr bool is_signed_v
= is_signed::value;
template constexpr bool is_unsigned_v
= is_unsigned::value;
template constexpr bool is_constructible_v
= is_constructible::value;
template constexpr bool is_default_constructible_v
= is_default_constructible::value;
template constexpr bool is_copy_constructible_v
= is_copy_constructible::value;
template constexpr bool is_move_constructible_v
= is_move_constructible::value;
template constexpr bool is_assignable_v
= is_assignable::value;
template constexpr bool is_copy_assignable_v
= is_copy_assignable::value;
template constexpr bool is_move_assignable_v
= is_move_assignable::value;
template constexpr bool is_destructible_v
= is_destructible::value;
template constexpr bool is_trivially_constructible_v
= is_trivially_constructible::value;
template constexpr bool is_trivially_default_constructible_v
= is_trivially_default_constructible::value;
template constexpr bool is_trivially_copy_constructible_v
= is_trivially_copy_constructible::value;
template constexpr bool is_trivially_move_constructible_v
= is_trivially_move_constructible::value;
template constexpr bool is_trivially_assignable_v
= is_trivially_assignable::value;
template constexpr bool is_trivially_copy_assignable_v
= is_trivially_copy_assignable::value;
template constexpr bool is_trivially_move_assignable_v
= is_trivially_move_assignable::value;
template constexpr bool is_trivially_destructible_v
= is_trivially_destructible::value;
template constexpr bool is_nothrow_constructible_v
= is_nothrow_constructible::value;
template constexpr bool is_nothrow_default_constructible_v
= is_nothrow_default_constructible::value;
template constexpr bool is_nothrow_copy_constructible_v
= is_nothrow_copy_constructible::value;
template constexpr bool is_nothrow_move_constructible_v
= is_nothrow_move_constructible::value;
template constexpr bool is_nothrow_assignable_v
= is_nothrow_assignable::value;
template constexpr bool is_nothrow_copy_assignable_v
= is_nothrow_copy_assignable::value;
template constexpr bool is_nothrow_move_assignable_v
= is_nothrow_move_assignable::value;
template constexpr bool is_nothrow_destructible_v
= is_nothrow_destructible::value;
template constexpr bool has_virtual_destructor_v
= has_virtual_destructor::value;
// See C++14 §20.10.5 , type property queries
template constexpr size_t alignment_of_v
= alignment_of::value;
template constexpr size_t rank_v
= rank::value;
template constexpr size_t extent_v
= extent::value;
// See C++14 §20.10.6 , type relations
template constexpr bool is_same_v
= is_same::value;
template constexpr bool is_base_of_v
= is_base_of ::value;
template constexpr bool is_convertible_v
= is_convertible::value;
// 3.3.2, Other type transformations
template class invocation_type; // not defined
template class invocation_type;
template class raw_invocation_type; // not defined
template class raw_invocation_type;
template
using invocation_type_t = typename invocation_type::type;
template
using raw_invocation_type_t = typename raw_invocation_type::type;
// 3.3.3, Logical operator traits
template struct conjunction;
template constexpr bool conjunction_v = conjunction::value;
template struct disjunction;
template constexpr bool disjunction_v = disjunction::value;
template struct negation;
template constexpr bool negation_v = negation::value;
// 3.3.4, Detection idiom
template using void_t = void;
struct nonesuch {
nonesuch() = delete;
~nonesuch() = delete;
nonesuch(nonesuch const&) = delete;
void operator=(nonesuch const&) = delete;
};
template class Op, class... Args>
using is_detected = see below;
template class Op, class... Args>
constexpr bool is_detected_v = is_detected::value;
template class Op, class... Args>
using detected_t = see below;
template class Op, class... Args>
using detected_or = see below;
template class Op, class... Args>
using detected_or_t = typename detected_or::type;
template class Op, class... Args>
using is_detected_exact = is_same>;
template class Op, class... Args>
constexpr bool is_detected_exact_v
= is_detected_exact::value;
template class Op, class... Args>
using is_detected_convertible = is_convertible, To>;
template class Op, class... Args>
constexpr bool is_detected_convertible_v
= is_detected_convertible::value;
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
This sub-clause contains templates that may be used to transform one type to another following some predefined rule.
Each of the templates in this subclause shall be a
Within this section, define the invocation parameters of INVOKE(f, t1, t2, ..., tN) as follows,
in which T1 is the possibly cv-qualified type of t1
and U1 denotes T1& if t1 is an lvalue
or T1&& if t1 is an rvalue:
f is a pointer to a member function of a class T
the U1 followed by
the parameters of f matched by t2, ..., tN.
N == 1 and f is a pointer to member data of a class T
the U1.
f is a class object,
the t1, ..., tN
of the best viable function (t1, ..., tN
among the function call operators of f.
f
matching t1, ... tN.
In all of the above cases,
if an argument tI matches the ellipsis in the function's tI.
S is defined as
struct S {
int f(double const &) const;
void operator()(int, int);
void operator()(char const *, int i = 2, int j = 3);
void operator()(...);
};
INVOKE(&S::f, S(), 3.5) are (S &&, double const &).INVOKE(S(), 1, 2) are (int, int).INVOKE(S(), "abc", 5) are (const char *, int).
The defaulted parameter j does not correspond to an argument.INVOKE(S(), locale(), 5) are (locale, int).
Arguments corresponding to ellipsis maintain their types.| Template | Condition | Comments |
|---|---|---|
template
|
Fn and all types in the parameter pack ArgTypes
shall be complete types, (possibly cv-qualified) void, or arrays of unknown bound.
|
see below |
template
|
Fn and all types in the parameter pack ArgTypes
shall be complete types, (possibly cv-qualified) void,
or arrays of unknown bound.
|
see below |
Access checking is performed as if in a context unrelated to Fn and ArgTypes.
Only the validity of the immediate context of the expression is considered.
The nested typedef raw_invocation_type shall be defined as follows.
If the expression INVOKE(declval
is ill-formed when treated as an unevaluated operand (type. Otherwise:
R denote result_of_t.Ti be the INVOKE(declval(), declval()...) .type shall name the function type R(T1, T2, ...).
The nested typedef invocation_type shall be defined as follows.
If raw_invocation_type does not exist, there shall be no member typedef type.
Otherwise:
A1, A2, … denote ArgTypes...R(T1, T2, …) denote raw_invocation_type_ttype shall name the function type R(U1, U2, …)
where Ui is decay_t if declval() is an rvalue
otherwise Ti.
This subclause describes type traits for applying logical operators to other type traits.
template struct conjunction : see below { };
The class template conjunction forms the logical
conjunction of its template type arguments. Every template type argument
shall be usable as a base class and shall have a static data member
value which is convertible to bool, is not
hidden, and is unambiguously available in the type.
The BaseCharacteristic of a specialization conjunction
is the first type B in the list true_type,
B1, …, BN for which B::value == false,
or if every B::value != false the BaseCharacteristic
is BN. conjunction
does not necessarily have a BaseCharacteristic of either true_type
or false_type.
— end note ]
For a specialization conjunction if
there is a template type argument Bi with Bi::value == false
then instantiating conjunction does
not require the instantiation of Bj::value for j > i.
&&.
— end note ]
template struct disjunction : see below { };
The class template disjunction forms the logical
disjunction of its template type arguments. Every template type argument
shall be usable as a base class and shall have a static data member
value which is convertible to bool, is not
hidden, and is unambiguously available in the type.
The BaseCharacteristic of a specialization disjunction
is the first type B in the list false_type,
B1, …, BN for which B::value != false,
or if every B::value == false the BaseCharacteristic
is BN. disjunction
does not necessarily have a BaseCharacteristic of either true_type
or false_type.
— end note ]
For a specialization disjunction if
there is a template type argument Bi with Bi::value != false
then instantiating disjunction does
not require the instantiation of Bj::value for j > i.
||.
— end note ]
template struct negation : integral_constant { };
The class template negation forms the logical negation of
its template type argument. The type negation is a
UnaryTypeTrait with a BaseCharacteristic of integral_constant.
template class Op, class... Args>
struct DETECTOR { // exposition only
using value_t = false_type;
using type = Default;
};
template class Op, class... Args>
struct DETECTOR>, Op, Args...> { // exposition only
using value_t = true_type;
using type = Op;
};
template class Op, class... Args>
using is_detected = typename DETECTOR::value_t;
template class Op, class... Args>
using detected_t = typename DETECTOR::type;
template class Op, class... Args>
using detected_or = DETECTOR;
// archetypal helper alias for a copy assignment operation:
template
using copy_assign_t = decltype(declval() = declval());
// plausible implementation for the is_assignable type trait:
template
using is_copy_assignable = is_detected;
// plausible implementation for an augmented is_assignable type trait
// that also checks the return type:
template
using is_canonical_copy_assignable = is_detected_exact;
— end example ]
// archetypal helper alias for a particular type member:
template
using diff_t = typename T::difference_type;
// alias the type member, if it exists, otherwise alias ptrdiff_t:
template
using difference_type = detected_or_t;
— end example ]
#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
// See C++14 §20.11.5 , ratio comparison
template constexpr bool ratio_equal_v
= ratio_equal::value;
template constexpr bool ratio_not_equal_v
= ratio_not_equal::value;
template constexpr bool ratio_less_v
= ratio_less::value;
template constexpr bool ratio_less_equal_v
= ratio_less_equal::value;
template constexpr bool ratio_greater_v
= ratio_greater::value;
template constexpr bool ratio_greater_equal_v
= ratio_greater_equal::value;
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
#include
namespace std {
namespace chrono {
namespace experimental {
inline namespace fundamentals_v2 {
// See C++14 §20.12.4 , customization traits
template constexpr bool treat_as_floating_point_v
= treat_as_floating_point::value;
} // namespace fundamentals_v2
} // namespace experimental
} // namespace chrono
} // namespace std
#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
// See C++14 §19.5 , System error support
template constexpr bool is_error_code_enum_v
= is_error_code_enum::value;
template constexpr bool is_error_condition_enum_v
= is_error_condition_enum::value;
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
propagate_constpropagate_const general
propagate_const is a wrapper around a pointer-like object type T
which treats the wrapped pointer as a pointer to const when
the wrapper is accessed through a const access path.
synopsisnamespace std {
namespace experimental {
inline namespace fundamentals_v2 {
template class propagate_const {
public:
typedef remove_reference_t())> element_type;
// 3.7.4, propagate_const constructors
constexpr propagate_const() = default;
propagate_const(const propagate_const& p) = delete;
constexpr propagate_const(propagate_const&& p) = default;
template
see below constexpr propagate_const(propagate_const&& pu);
template
see below constexpr propagate_const(U&& u);
// 3.7.5, propagate_const assignment
propagate_const& operator=(const propagate_const& p) = delete;
constexpr propagate_const& operator=(propagate_const&& p) = default;
template
constexpr propagate_const& operator=(propagate_const&& pu);
template
constexpr propagate_const& operator=(U&& u);
// 3.7.6, propagate_const const observers
explicit constexpr operator bool() const;
constexpr const element_type* operator->() const;
constexpr operator const element_type*() const; // Not always defined
constexpr const element_type& operator*() const;
constexpr const element_type* get() const;
// 3.7.7, propagate_const non-const observers
constexpr element_type* operator->();
constexpr operator element_type*(); // Not always defined
constexpr element_type& operator*();
constexpr element_type* get();
// 3.7.8, propagate_const modifiers
constexpr void swap(propagate_const& pt) noexcept(see below);
private:
T t_; //exposition only
};
// 3.7.9, propagate_const relational operators
template
constexpr bool operator==(const propagate_const& pt, nullptr_t);
template
constexpr bool operator==(nullptr_t, const propagate_const& pu);
template
constexpr bool operator!=(const propagate_const& pt, nullptr_t);
template
constexpr bool operator!=(nullptr_t, const propagate_const& pu);
template
constexpr bool operator==(const propagate_const& pt, const propagate_const& pu);
template
constexpr bool operator!=(const propagate_const& pt, const propagate_const& pu);
template
constexpr bool operator<(const propagate_const& pt, const propagate_const& pu);
template
constexpr bool operator>(const propagate_const& pt, const propagate_const& pu);
template
constexpr bool operator<=(const propagate_const& pt, const propagate_const& pu);
template
constexpr bool operator>=(const propagate_const& pt, const propagate_const& pu);
template
constexpr bool operator==(const propagate_const& pt, const U& u);
template
constexpr bool operator!=(const propagate_const& pt, const U& u);
template
constexpr bool operator<(const propagate_const& pt, const U& u);
template
constexpr bool operator>(const propagate_const& pt, const U& u);
template
constexpr bool operator<=(const propagate_const& pt, const U& u);
template
constexpr bool operator>=(const propagate_const& pt, const U& u);
template
constexpr bool operator==(const T& t, const propagate_const& pu);
template
constexpr bool operator!=(const T& t, const propagate_const& pu);
template
constexpr bool operator<(const T& t, const propagate_const& pu);
template
constexpr bool operator>(const T& t, const propagate_const& pu);
template
constexpr bool operator<=(const T& t, const propagate_const& pu);
template
constexpr bool operator>=(const T& t, const propagate_const& pu);
// 3.7.10, propagate_const specialized algorithms
template
constexpr void swap(propagate_const& pt, propagate_const& pt2) noexcept(see below);
// 3.7.11, propagate_const underlying pointer access
template
constexpr const T& get_underlying(const propagate_const& pt) noexcept;
template
constexpr T& get_underlying(propagate_const& pt) noexcept;
} // inline namespace fundamentals_v2
} // namespace experimental
// 3.7.12, propagate_const hash support
template struct hash;
template
struct hash>;
// 3.7.13, propagate_const comparison function objects
template struct equal_to;
template
struct equal_to>;
template struct not_equal_to;
template
struct not_equal_to>;
template struct less;
template
struct less>;
template struct greater;
template
struct greater>;
template struct less_equal;
template
struct less_equal>;
template struct greater_equal;
template
struct greater_equal>;
} // namespace std
propagate_const requirements on T
T shall be an object pointer type or a class type for which
decltype(*declval is an lvalue reference; otherwise
the program is ill-formed.
If T is an array type, reference type, pointer to function type or
pointer to (possibly cv-qualified) void, then the program is
ill-formed.
propagate_const is well-formed
— end note ]
propagate_const requirements on class type T
If T is class
type then it shall satisfy the following requirements. In this sub-clause
t denotes a non-const lvalue of type T, ct
is a const T& bound to t, element_type denotes
an object type.
T and const T shall be contextually convertible to bool.
If T is implicitly convertible to element_type*,
(element_type*)t == t.get() shall be true.
If const T is implicitly convertible to const element_type*,
(const element_type*)ct == ct.get() shall be true.
| Expression | Return type | Pre-conditions | Operational semantics |
|---|---|---|---|
t.get() |
element_type* |
||
ct.get() |
const element_type* or element_type* |
|
t.get() == ct.get(). |
*t |
element_type& |
t.get() != nullptr |
*t refers to the same object as *(t.get()) |
*ct |
const element_type& or element_type&
|
ct.get() != nullptr |
*ct refers to the same object as *(ct.get())
|
t.operator->() |
element_type* |
t.get() != nullptr |
t.operator->() == t.get() |
ct.operator->() |
const element_type* or element_type* |
ct.get() != nullptr |
ct.operator->() == ct.get() |
(bool)t |
bool |
|
(bool)t is equivalent to t.get() != nullptr |
(bool)ct |
bool |
|
(bool)ct is equivalent to ct.get() != nullptr |
propagate_const constructors
explicit. This is typically implemented by declaring two such
constructors, of which at most one participates in overload resolution.
— end note ]
template
see below constexpr propagate_const(propagate_const&& pu);
is_constructible_v.
The constructor is specified as explicit if and only if
!is_convertible_v.
t_ as if
direct-non-list-initializing an object of type T with the
expression std::move(pu.t_).
template
see below constexpr propagate_const(U&& u);
is_constructible_v
and decay_t is not a specialization of propagate_const.
The constructor is specified as explicit if and only if
!is_convertible_v.
t_ as if
direct-non-list-initializing an object of type T with
the expression std::forward(u).
propagate_const assignmenttemplate
constexpr propagate_const& operator=(propagate_const&& pu);
U is implicitly convertible to T.
t_ = std::move(pu.t_).*this.template
constexpr propagate_const& operator=(U&& u);
U is implicitly convertible to T and
decay_t is not a specialization of propagate_const.
t_ = std::forward(u).*this.propagate_const const observersexplicit constexpr operator bool() const;
(bool)t_.constexpr const element_type* operator->() const;
get() != nullptr.get().constexpr operator const element_type*() const;
get().T is an object pointer type or
has an implicit conversion to const element_type*.
constexpr const element_type& operator*() const;
get() != nullptr.*get().constexpr const element_type* get() const;
t_ if T is an object pointer type,
otherwise t_.get().
propagate_const non-const observersconstexpr element_type* operator->();
get() != nullptr.get().constexpr operator element_type*();
get().T is an object pointer type or
has an implicit conversion to element_type*.
constexpr element_type& operator*();
get() != nullptr.*get().constexpr element_type* get();
t_ if T is an object pointer type,
otherwise t_.get().
propagate_const modifiersconstexpr void swap(propagate_const& pt) noexcept(see below);
The constant-expression in the exception-specification is noexcept(swap(t_, pt.t_)).
swap(t_, pt.t_).propagate_const relational operatorstemplate
constexpr bool operator==(const propagate_const& pt, nullptr_t);
pt.t_ == nullptr.template
constexpr bool operator==(nullptr_t, const propagate_const& pt);
nullptr == pt.t_.template
constexpr bool operator!=(const propagate_const& pt, nullptr_t);
pt.t_ != nullptr.template
constexpr bool operator!=(nullptr_t, const propagate_const& pt);
nullptr != pt.t_.template
constexpr bool operator==(const propagate_const& pt, const propagate_const& pu);
pt.t_ == pu.t_.template
constexpr bool operator!=(const propagate_const& pt, const propagate_const& pu);
pt.t_ != pu.t_.template
constexpr bool operator<(const propagate_const& pt, const propagate_const& pu);
pt.t_ < pu.t_.template
constexpr bool operator>(const propagate_const& pt, const propagate_const& pu);
pt.t_ > pu.t_.template
constexpr bool operator<=(const propagate_const& pt, const propagate_const& pu);
pt.t_ <= pu.t_.template
constexpr bool operator>=(const propagate_const& pt, const propagate_const& pu);
pt.t_ >= pu.t_.template
constexpr bool operator==(const propagate_const& pt, const U& u);
pt.t_ == u.template
constexpr bool operator!=(const propagate_const& pt, const U& u);
pt.t_ != u.template
constexpr bool operator<(const propagate_const& pt, const U& u);
pt.t_ < u.template
constexpr bool operator>(const propagate_const& pt, const U& u);
pt.t_ > u.template
constexpr bool operator<=(const propagate_const& pt, const U& u);
pt.t_ <= u.template
constexpr bool operator>=(const propagate_const& pt, const U& u);
pt.t_ >= u.template
constexpr bool operator==(const T& t, const propagate_const& pu);
t == pu.t_.template
constexpr bool operator!=(const T& t, const propagate_const& pu);
t != pu.t_.template
constexpr bool operator<(const T& t, const propagate_const& pu);
t < pu.t_.template
constexpr bool operator>(const T& t, const propagate_const& pu);
t > pu.t_.template
constexpr bool operator<=(const T& t, const propagate_const& pu);
t <= pu.t_.template
constexpr bool operator>=(const T& t, const propagate_const& pu);
t >= pu.t_.propagate_const specialized algorithmstemplate
constexpr void swap(propagate_const& pt1, propagate_const& pt2) noexcept(see below);
The constant-expression in the exception-specification is noexcept(swap(pt1.t_, pt2.t_)).
swap(pt1.t_, pt2.t_).propagate_const underlying pointer accessAccess to the underlying object pointer type is through free functions rather than member functions. These functions are intended to resemble cast operations to encourage caution when using them.
template
constexpr const T& get_underlying(const propagate_const& pt) noexcept;
template
constexpr T& get_underlying(propagate_const& pt) noexcept;
propagate_const hash supporttemplate
struct hash>;
For an object p of type propagate_const,
hash
shall evaluate to the same value as hash.
hash shall be well-formed and well-defined,
and shall meet the requirements of class template hash.
propagate_const comparison function objectstemplate
struct equal_to>;
For objects p, q of type propagate_const,
equal_to
shall evaluate to the same value as equal_to.
equal_to shall be well-formed and well-defined.
template
struct not_equal_to>;
For objects p, q of type propagate_const,
not_equal_to
shall evaluate to the same value as not_equal_to.
not_equal_to shall be well-formed and well-defined.
template
struct less>;
For objects p, q of type propagate_const,
less
shall evaluate to the same value as less.
less shall be well-formed and well-defined.
template
struct greater>;
For objects p, q of type propagate_const,
greater
shall evaluate to the same value as greater.
greater shall be well-formed and well-defined.
template
struct less_equal>;
For objects p, q of type propagate_const,
less_equal
shall evaluate to the same value as less_equal.
less_equal shall be well-formed and well-defined.
template
struct greater_equal>;
For objects p, q of type propagate_const,
greater_equal
shall evaluate to the same value as greater_equal.
greater_equal shall be well-formed and well-defined.
synopsis#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
// See C++14 §20.9.9 , Function object binders
template constexpr bool is_bind_expression_v
= is_bind_expression::value;
template constexpr int is_placeholder_v
= is_placeholder::value;
// 4.2, Class template function
template class function; // undefined
template class function;
template
void swap(function&, function&);
template
bool operator==(const function&, nullptr_t) noexcept;
template
bool operator==(nullptr_t, const function&) noexcept;
template
bool operator!=(const function&, nullptr_t) noexcept;
template
bool operator!=(nullptr_t, const function&) noexcept;
// 4.3, Searchers
template>
class default_searcher;
template::value_type>,
class BinaryPredicate = equal_to<>>
class boyer_moore_searcher;
template::value_type>,
class BinaryPredicate = equal_to<>>
class boyer_moore_horspool_searcher;
template>
default_searcher
make_default_searcher(ForwardIterator pat_first, ForwardIterator pat_last,
BinaryPredicate pred = BinaryPredicate());
template::value_type>,
class BinaryPredicate = equal_to<>>
boyer_moore_searcher
make_boyer_moore_searcher(
RandomAccessIterator pat_first, RandomAccessIterator pat_last,
Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());
template::value_type>,
class BinaryPredicate = equal_to<>>
boyer_moore_horspool_searcher
make_boyer_moore_horspool_searcher(
RandomAccessIterator pat_first, RandomAccessIterator pat_last,
Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());
// 4.4, Function template not_fn
template unspecified not_fn(F&& f);
} // namespace fundamentals_v2
} // namespace experimental
template
struct uses_allocator, Alloc>;
} // namespace std
function
The specification of all declarations within this sub-clause std::experimental::function uses
std::bad_function_call, there is no additional type std::experimental::bad_function_call
— end note ]
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
template class function; // undefined
template
class function {
public:
typedef R result_type;
typedef T1 argument_type;
typedef T1 first_argument_type;
typedef T2 second_argument_type;
typedef erased_type allocator_type;
function() noexcept;
function(nullptr_t) noexcept;
function(const function&);
function(function&&);
template function(F);
template function(allocator_arg_t, const A&) noexcept;
template function(allocator_arg_t, const A&,
nullptr_t) noexcept;
template function(allocator_arg_t, const A&,
const function&);
template function(allocator_arg_t, const A&,
function&&);
template function(allocator_arg_t, const A&, F);
function& operator=(const function&);
function& operator=(function&&);
function& operator=(nullptr_t) noexcept;
template function& operator=(F&&);
template function& operator=(reference_wrapper);
~function();
void swap(function&);
template void assign(F&&, const A&);
explicit operator bool() const noexcept;
R operator()(ArgTypes...) const;
const type_info& target_type() const noexcept;
template T* target() noexcept;
template const T* target() const noexcept;
pmr::memory_resource* get_memory_resource();
};
template
bool operator==(const function&, nullptr_t) noexcept;
template
bool operator==(nullptr_t, const function&) noexcept;
template
bool operator!=(const function&, nullptr_t) noexcept;
template
bool operator!=(nullptr_t, const function&) noexcept;
template
void swap(function&, function&);
} // namespace fundamentals_v2
} // namespace experimental
template
struct uses_allocator, Alloc>
: true_type { };
} // namespace std
function construct/copy/destroy
When a function constructor that takes a first argument of type allocator_arg_t is invoked,
the second argument is treated as a experimental::function class template,
then that move or copy is performed by get_memory_resource().
In the following descriptions, let ALLOCATOR_OF(f) be the allocator specified in the construction of function f,
or allocator if no allocator was specified.
function& operator=(const function& f);
function(allocator_arg, ALLOCATOR_OF(*this), f).swap(*this);*this.function& operator=(function&& f);
function(allocator_arg, ALLOCATOR_OF(*this), std::move(f)).swap(*this);*this.function& operator=(nullptr_t) noexcept;
*this != nullptr, destroys the target of this.!(*this).
The memory resource returned by get_memory_resource() after the assignment is equivalent to the memory resource before the assignment.
get_memory_resource() might change
— end note ]
*this.template function& operator=(F&& f);
function(allocator_arg, ALLOCATOR_OF(*this), std::forward(f)).swap(*this); *this.template function& operator=(reference_wrapper f);
function(allocator_arg, ALLOCATOR_OF(*this), f).swap(*this);*this.function modifiersvoid swap(function& other);
*this->get_memory_resource() == *other.get_memory_resource().*this and other.*this and other are not interchanged.
This sub-clause provides function object types (pat_first, pat_last)first, last)
Each specialization of a class template specified in this sub-clause CopyConstructible and CopyAssignable requirements.
Template parameters named ForwardIterator, ForwardIterator1, ForwardIterator2, RandomAccessIterator, RandomAccessIterator1, RandomAccessIterator2, and BinaryPredicate of templates specified in this sub-clause Hash shall meet the requirements as specified in
The Boyer-Moore searcher implements the Boyer-Moore search algorithm. The Boyer-Moore-Horspool searcher implements the Boyer-Moore-Horspool search algorithm. In general, the Boyer-Moore searcher will use more memory and give better run-time performance than Boyer-Moore-Horspool
default_searchertemplate>
class default_searcher {
public:
default_searcher(ForwardIterator1 pat_first, ForwardIterator1 pat_last,
BinaryPredicate pred = BinaryPredicate());
template
ForwardIterator2
operator()(ForwardIterator2 first, ForwardIterator2 last) const;
private:
ForwardIterator1 pat_first_; // exposition only
ForwardIterator1 pat_last_; // exposition only
BinaryPredicate pred_; // exposition only
};
default_searcher(ForwardIterator pat_first, ForwardIterator pat_last,
BinaryPredicate pred = BinaryPredicate());
default_searcher object, initializing pat_first_ with pat_first, pat_last_ with pat_last, and pred_ with pred.BinaryPredicate or ForwardIterator1.template
ForwardIterator2 operator()(ForwardIterator2 first, ForwardIterator2 last) const;
return std::search( first, last, pat_first_, pat_last_, pred_);default_searcher creation functionstemplate>
default_searcher
make_default_searcher(ForwardIterator pat_first, ForwardIterator pat_last,
BinaryPredicate pred = BinaryPredicate());
return default_searcher( pat_first, pat_last, pred); boyer_moore_searchertemplate::value_type>,
class BinaryPredicate = equal_to<>>
class boyer_moore_searcher {
public:
boyer_moore_searcher(RandomAccessIterator1 pat_first, RandomAccessIterator1 pat_last,
Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());
template
RandomAccessIterator2
operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const;
private:
RandomAccessIterator1 pat_first_; // exposition only
RandomAccessIterator1 pat_last_; // exposition only
Hash hash_; // exposition only
BinaryPredicate pred_; // exposition only
};
boyer_moore_searcher(RandomAccessIterator1 pat_first, RandomAccessIterator1 pat_last,
Hash hf = Hash(),
BinaryPredicate pred = BinaryPredicate());
RandomAccessIterator1 shall meet the DefaultConstructible, CopyConstructible, and CopyAssignable requirements.A and B of the type iterator_traits::value_type , if pred(A,B)==true, then hf(A)==hf(B) shall be true.boyer_moore_searcher object, initializing pat_first_ with pat_first, pat_last_ with pat_last, hash_ with hf, and pred_ with pred.RandomAccessIterator1,
or by the default constructor, copy constructor, or the copy assignment operator of the value type of RandomAccessIterator1,
or the copy constructor or operator() of BinaryPredicate or Hash.
May throw bad_alloc if additional memory needed for internal data structures cannot be allocated.template
RandomAccessIterator2 operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const;
RandomAccessIterator1 and RandomAccessIterator2 shall have the same value type.i in the range first, last - (pat_last_ - pat_first_))n less than pat_last_ - pat_first_ the following condition holds:
pred(*(i + n), *(pat_first_ + n)) != false.
Returns first if pat_first_, pat_last_)last if no such iterator is found.
(last - first) * (pat_last_ - pat_first_) applications of the predicate.boyer_moore_searcher creation functionstemplate::value_type>,
class BinaryPredicate = equal_to<>>
boyer_moore_searcher
make_boyer_moore_searcher(RandomAccessIterator pat_first, RandomAccessIterator pat_last,
Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());
return boyer_moore_searcher( pat_first, pat_last, hf, pred); boyer_moore_horspool_searcher
template::value_type>,
class BinaryPredicate = equal_to<>>
class boyer_moore_horspool_searcher {
public:
boyer_moore_horspool_searcher(RandomAccessIterator1 pat_first, RandomAccessIterator1 pat_last,
Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());
template
RandomAccessIterator2
operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const;
private:
RandomAccessIterator1 pat_first_; // exposition only
RandomAccessIterator1 pat_last_; // exposition only
Hash hash_; // exposition only
BinaryPredicate pred_; // exposition only
};
boyer_moore_horspool_searcher(
RandomAccessIterator1 pat_first, RandomAccessIterator1 pat_last,
Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());
RandomAccessIterator1 shall meet the DefaultConstructible, CopyConstructible, and CopyAssignable requirements.A and B of the type iterator_traits::value_type ,
if pred(A,B)==true, then hf(A)==hf(B) shall be true.boyer_moore_horspool_searcher object, initializing pat_first_ with pat_first,
pat_last_ with pat_last, hash_ with hf, and pred_ with pred.RandomAccessIterator1,
or by the default constructor, copy constructor, or the copy assignment operator of the value type of RandomAccessIterator1
or the copy constructor or operator() of BinaryPredicate or Hash.
May throw bad_alloc if additional memory needed for internal data structures cannot be allocated..
template
RandomAccessIterator2 operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const;
RandomAccessIterator1 and RandomAccessIterator2 shall have the same value type.i in the range first, last - (pat_last_ - pat_first_))n less than pat_last_ - pat_first_ the following condition holds:
pred(*(i + n), *(pat_first_ + n)) != false.
Returns first if pat_first_, pat_last_)last if no such iterator is found.
(last - first) * (pat_last_ - pat_first_) applications of the predicate.boyer_moore_horspool_searcher creation functionstemplate::value_type>,
class BinaryPredicate = equal_to<>>
boyer_moore_searcher_horspool
make_boyer_moore_horspool_searcher(
RandomAccessIterator pat_first, RandomAccessIterator pat_last,
Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());
return boyer_moore_horspool_searcher( pat_first, pat_last, hf, pred); not_fntemplate unspecified not_fn(F&& f);
In the text that follows:
FD is the type decay_t,fd is an lvalue of type FD constructed from std::forward(f), fn is a forwarding call wrapper created as a result of not_fn(f),is_constructible::value shall be true.
fd shall be a callable object (fn such that the expression fn(a1, a2, ..., aN)
is equivalent to !INVOKE(fd, a1, a2, ..., aN) (fd throws an exception.MoveConstructible.
If FD satisfies the requirements of CopyConstructible, then
the return type shall satisfy the requirements of CopyConstructible.
FD is MoveConstructible.
— end note ]
not_fn can usually provide a better solution than using the negators not1 and not2
— end note ]
This subclause describes class template optional that represents optional objects. An optional object for object types
is an object that contains the storage for another object and manages
the lifetime of this contained object, if any. The contained object may
be initialized after the optional object has been initialized, and may
be destroyed before the optional object has been destroyed. The
initialization state of the contained object is tracked by the optional
object.
synopsisnamespace std {
namespace experimental {
inline namespace fundamentals_v2 {
// 5.3, optional for object types
template class optional;
// 5.4, In-place construction
struct in_place_t{};
constexpr in_place_t in_place{};
// 5.5, No-value state indicator
struct nullopt_t{see below};
constexpr nullopt_t nullopt(unspecified);
// 5.6, Class bad_optional_access
class bad_optional_access;
// 5.7, Relational operators
template
constexpr bool operator==(const optional&, const optional&);
template
constexpr bool operator!=(const optional&, const optional&);
template
constexpr bool operator<(const optional&, const optional&);
template
constexpr bool operator>(const optional&, const optional&);
template
constexpr bool operator<=(const optional&, const optional&);
template
constexpr bool operator>=(const optional&, const optional&);
// 5.8, Comparison with nullopt
template constexpr bool operator==(const optional&, nullopt_t) noexcept;
template constexpr bool operator==(nullopt_t, const optional&) noexcept;
template constexpr bool operator!=(const optional&, nullopt_t) noexcept;
template constexpr bool operator!=(nullopt_t, const optional&) noexcept;
template constexpr bool operator<(const optional&, nullopt_t) noexcept;
template constexpr bool operator<(nullopt_t, const optional&) noexcept;
template constexpr bool operator<=(const optional&, nullopt_t) noexcept;
template constexpr bool operator<=(nullopt_t, const optional&) noexcept;
template constexpr bool operator>(const optional&, nullopt_t) noexcept;
template constexpr bool operator>(nullopt_t, const optional&) noexcept;
template constexpr bool operator>=(const optional&, nullopt_t) noexcept;
template constexpr bool operator>=(nullopt_t, const optional&) noexcept;
// 5.9, Comparison with T
template constexpr bool operator==(const optional&, const T&);
template constexpr bool operator==(const T&, const optional&);
template constexpr bool operator!=(const optional&, const T&);
template constexpr bool operator!=(const T&, const optional&);
template constexpr bool operator<(const optional&, const T&);
template constexpr bool operator<(const T&, const optional&);
template constexpr bool operator<=(const optional&, const T&);
template constexpr bool operator<=(const T&, const optional&);
template constexpr bool operator>(const optional&, const T&);
template constexpr bool operator>(const T&, const optional&);
template constexpr bool operator>=(const optional&, const T&);
template constexpr bool operator>=(const T&, const optional&);
// 5.10, Specialized algorithms
template void swap(optional&, optional&) noexcept(see below);
template constexpr optional<see below> make_optional(T&&);
} // namespace fundamentals_v2
} // namespace experimental
// 5.11, Hash support
template struct hash;
template struct hash>;
} // namespace std
A program that necessitates the instantiation of template optional for a reference type, or for possibly cv-qualified types in_place_t or nullopt_t is ill-formed.
optional for object typestemplate
class optional
{
public:
typedef T value_type;
// 5.3.1, Constructors
constexpr optional() noexcept;
constexpr optional(nullopt_t) noexcept;
optional(const optional&);
optional(optional&&) noexcept(see below);
constexpr optional(const T&);
constexpr optional(T&&);
template constexpr explicit optional(in_place_t, Args&&...);
template
constexpr explicit optional(in_place_t, initializer_list, Args&&...);
// 5.3.2, Destructor
~optional();
// 5.3.3, Assignment
optional& operator=(nullopt_t) noexcept;
optional& operator=(const optional&);
optional& operator=(optional&&) noexcept(see below);
template optional& operator=(U&&);
template void emplace(Args&&...);
template
void emplace(initializer_list, Args&&...);
// 5.3.4, Swap
void swap(optional&) noexcept(see below);
// 5.3.5, Observers
constexpr T const* operator ->() const;
constexpr T* operator ->();
constexpr T const& operator *() const &;
constexpr T& operator *() &;
constexpr T&& operator *() &&;
constexpr const T&& operator *() const &&;
constexpr explicit operator bool() const noexcept;
constexpr T const& value() const &;
constexpr T& value() &;
constexpr T&& value() &&;
constexpr const T&& value() const &&;
template constexpr T value_or(U&&) const &;
template constexpr T value_or(U&&) &&;
private:
T* val; // exposition only
};
Any instance of optional at any given time either contains a value or does not contain a value.
When an instance of optional contains a value,
it means that an object of type T, referred to as the optional object's contained value,
is allocated within the storage of the optional object.
Implementations are not permitted to use additional storage, such as dynamic memory, to allocate its contained value.
The contained value shall be allocated in a region of the optional storage suitably aligned for the type T.
When an object of type optional is contextually converted to bool,
the conversion returns true if the object contains a value;
otherwise the conversion returns false.
Member val is provided for exposition only. When an optional object contains a value, val points to the contained value.
T shall be an object type and shall satisfy the requirements of Destructible (Table 24).
constexpr optional() noexcept; constexpr optional(nullopt_t) noexcept;
*this does not contain a value.T these constructors shall be constexpr constructors (optional(const optional& rhs);
is_copy_constructible_v is true.rhs contains a value, initializes the contained value as if
direct-non-list-initializing an object of type T with the expression *rhs.bool(rhs) == bool(*this).T.optional(optional&& rhs) noexcept(see below);
is_move_constructible_v is true.rhs contains a value, initializes the contained value as if
direct-non-list-initializing an object of type T with the expression std::move(*rhs).
bool(rhs) is unchanged.bool(rhs) == bool(*this).T.noexcept is equivalent to:is_nothrow_move_constructible_vconstexpr optional(const T& v);
is_copy_constructible_v is true.T with the expression v.*this contains a value.T.T's selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor.constexpr optional(T&& v);
is_move_constructible_v is true.T with the expression std::move(v).*this contains a value.T.T's selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor.template constexpr explicit optional(in_place_t, Args&&... args);
is_constructible_v is true.T with the arguments std::forward(args)... .*this contains a value.T.T's constructor selected for the initialization is a constexpr constructor, this constructor shall be a constexpr constructor.template
constexpr explicit optional(in_place_t, initializer_list il, Args&&... args);
is_constructible_v&, Args&&...> is true.T with the arguments il, std::forward(args)... .*this contains a value.T.is_constructible_v&, Args&&...> is true.
If T's constructor selected for the initialization is a constexpr constructor, this constructor shall be a constexpr constructor.~optional();
is_trivially_destructible_v != true and *this contains a value, calls val->T::~T().is_trivially_destructible_v == true then this destructor shall be a trivial destructor.optional& operator=(nullopt_t) noexcept;
*this contains a value, calls val->T::~T() to destroy the contained value; otherwise no effect.*this.*this does not contain a value.optional& operator=(const optional& rhs);
is_copy_constructible_v is true and is_copy_assignable_v is true.*this contains a value |
*this does not contain a value |
|
|---|---|---|
rhs contains a value |
assigns *rhs to the contained value |
initializes the contained value as if direct-non-list-initializing an object of type T with *rhs |
rhs does not contain a value |
destroys the contained value by calling val->T::~T() |
no effect |
*this.bool(rhs) == bool(*this).bool(*this) remains unchanged.
If an exception is thrown during the call to T's copy constructor, no effect.
If an exception is thrown during the call to T's copy assignment,
the state of its contained value is as defined by the exception safety guarantee of T's copy assignment.
optional& operator=(optional&& rhs) noexcept(see below);
is_move_constructible_v is true and is_move_assignable_v is true.bool(rhs) remains unchanged.
*this contains a value |
*this does not contain a value |
|
|---|---|---|
rhs contains a value |
assigns std::move(*rhs) to the contained value |
initializes the contained value as if direct-non-list-initializing an object of type T with std::move(*rhs) |
rhs does not contain a value |
destroys the contained value by calling val->T::~T() |
no effect |
*this.bool(rhs) == bool(*this).The expression inside noexcept is equivalent to:
is_nothrow_move_assignable_v && is_nothrow_move_constructible_v
If any exception is thrown, the result of the expression bool(*this) remains unchanged.
If an exception is thrown during the call to T's move constructor,
the state of *rhs.val is determined by the exception safety guarantee of T's move constructor.
If an exception is thrown during the call to T's move assignment,
the state of *val and *rhs.val is determined by the exception safety guarantee of T's move assignment.
template optional& operator=(U&& v);
is_constructible_v is true and is_assignable_v is true.*this contains a value, assigns std::forward(v) to the contained value; otherwise initializes the contained value as if direct-non-list-initializing object of type T with std::forward(v).*this.*this contains a value.If any exception is thrown, the result of the expression bool(*this) remains unchanged. If an exception is thrown during the call to T's constructor, the state of v is determined by the exception safety guarantee of T's constructor. If an exception is thrown during the call to T's assignment, the state of *val and v is determined by the exception safety guarantee of T's assignment.
The function shall not participate in overload resolution unless
is_same_v is true.
T == U is to guarantee that assignment of the form o = {} is unambiguous.template void emplace(Args&&... args);
is_constructible_v is true.*this = nullopt. Then initializes the contained value as if direct-non-list-initializing an object of type T with the arguments std::forward(args)... .*this contains a value.T.T's constructor, *this does not contain a value, and the previous *val (if any) has been destroyed.template void emplace(initializer_list il, Args&&... args);
*this = nullopt. Then initializes the contained value as if direct-non-list-initializing an object of type T with the arguments il, std::forward(args)... .*this contains a value.T.If an exception is thrown during the call to T's constructor, *this does not contain a value, and the previous *val (if any) has been destroyed.
The function shall not participate in overload resolution unless is_constructible_v is true.
void swap(optional& rhs) noexcept(see below);
T shall be swappable and is_move_constructible_v is true.*this contains a value |
*this does not contain a value |
|
|---|---|---|
rhs contains a value |
calls swap(*(*this), *rhs) |
initializes the contained value of *this as if
direct-non-list-initializing an object of type T with the expression std::move(*rhs),
followed by rhs.val->T::~T();
postcondition is that *this contains a value and rhs does not contain a value |
rhs does not contain a value |
initializes the contained value of rhs as if
direct-non-list-initializing an object of type T with the expression std::move(*(*this)),
followed by val->T::~T();
postcondition is that *this does not contain a value and rhs contains a value |
no effect |
The expression inside noexcept is equivalent to:
is_nothrow_move_constructible_v && noexcept(swap(declval(), declval()))
If any exception is thrown, the results of the expressions bool(*this) and bool(rhs) remain unchanged.
If an exception is thrown during the call to function swap
the state of *val and *rhs.val is determined by the exception safety guarantee of swap for lvalues of T.
If an exception is thrown during the call to T's move constructor,
the state of *val and *rhs.val is determined by the exception safety guarantee of T's move constructor.
constexpr T const* operator->() const; constexpr T* operator->();
*this contains a value.val.T is a user-defined type with overloaded unary operator&, these functions shall be constexpr functions.constexpr T const& operator*() const &; constexpr T& operator*() &;
*this contains a value.*val.constexpr functions.constexpr T&& operator*() &&; constexpr const T&& operator*() const &&;
*this contains a value.return std::move(*val);constexpr explicit operator bool() const noexcept;
true if and only if *this contains a value.constexpr function.constexpr T const& value() const &; constexpr T& value() &;
return bool(*this) ? *val : throw bad_optional_access();
constexpr T&& value() &&; constexpr const T&& value() const &&;
return bool(*this) ? std::move(*val) : throw bad_optional_access();template constexpr T value_or(U&& v) const &;
return bool(*this) ? **this : static_cast(std::forward(v)); is_copy_constructible_v && is_convertible_v is false,
the program is ill-formed.template T value_or(U&& v) &&;
return bool(*this) ? std::move(**this) : static_cast(std::forward(v)); is_move_constructible_v && is_convertible_v is false,
the program is ill-formed.struct in_place_t{}; constexpr in_place_t in_place{};
The struct in_place_t is an empty structure type used as a unique type to disambiguate constructor and function overloading.
Specifically, optional has a constructor with in_place_t as the first parameter followed by a parameter pack;
this indicates that T should be constructed in-place
(as if by a call to a placement new expression) with the forwarded pack
expansion as arguments for the initialization of T.
struct nullopt_t{see below}; constexpr nullopt_t nullopt(unspecified);
The struct nullopt_t is an empty structure type used as a unique type to indicate the state of not containing a value for optional objects.
In particular, optional has a constructor with nullopt_t as a single argument;
this indicates that an optional object not containing a value shall be constructed.
Type nullopt_t shall not have a default constructor. It shall be a literal type. Constant nullopt shall be initialized with an argument of literal type.
bad_optional_accessclass bad_optional_access : public logic_error {
public:
bad_optional_access();
};
The class bad_optional_access
defines the type of objects thrown as exceptions to report the
situation where an attempt is made to access the value of an optional
object that does not contain a value.
bad_optional_access();
bad_optional_access.what() returns an implementation-defined NTBS.template constexpr bool operator==(const optional& x, const optional& y);
T shall meet the requirements of EqualityComparable.bool(x) != bool(y), false; otherwise if bool(x) == false, true; otherwise *x == *y.*x == *y is a core constant expression,
shall be constexpr functions.template constexpr bool operator!=(const optional& x, const optional& y);
!(x == y).template constexpr bool operator<(const optional& x, const optional& y);
*x < *y shall be well-formed
and its result shall be convertible to bool.!y, false;
otherwise, if !x, true;
otherwise *x < *y.*x < *y is a core constant expression,
shall be constexpr functions.template constexpr bool operator>(const optional& x, const optional& y);
y < x.template constexpr bool operator<=(const optional& x, const optional& y);
!(y < x).template constexpr bool operator>=(const optional& x, const optional& y);
!(x < y).nullopttemplate constexpr bool operator==(const optional& x, nullopt_t) noexcept; template constexpr bool operator==(nullopt_t, const optional& x) noexcept;
!x.template constexpr bool operator!=(const optional& x, nullopt_t) noexcept; template constexpr bool operator!=(nullopt_t, const optional& x) noexcept;
bool(x).template constexpr bool operator<(const optional& x, nullopt_t) noexcept;
false.template constexpr bool operator<(nullopt_t, const optional& x) noexcept;
bool(x).template constexpr bool operator<=(const optional& x, nullopt_t) noexcept;
!x.template constexpr bool operator<=(nullopt_t, const optional& x) noexcept;
true.template constexpr bool operator>(const optional& x, nullopt_t) noexcept;
bool(x).template constexpr bool operator>(nullopt_t, const optional& x) noexcept;
false.template constexpr bool operator>=(const optional& x, nullopt_t) noexcept;
true.template constexpr bool operator>=(nullopt_t, const optional& x) noexcept;
!x.Ttemplate constexpr bool operator==(const optional& x, const T& v);
bool(x) ? *x == v : false.template constexpr bool operator==(const T& v, const optional& x);
bool(x) ? v == *x : false.template constexpr bool operator!=(const optional& x, const T& v);
bool(x) ? !(*x == v) : true.template constexpr bool operator!=(const T& v, const optional& x);
bool(x) ? !(v == *x) : true.template constexpr bool operator<(const optional& x, const T& v);
bool(x) ? *x < v : true.template constexpr bool operator<(const T& v, const optional& x);
bool(x) ? v < *x : false.template constexpr bool operator<=(const optional& x, const T& v);
!(x > v).template constexpr bool operator<=(const T& v, const optional& x);
!(v > x).template constexpr bool operator>(const optional& x, const T& v);
bool(x) ? v < *x : false.template constexpr bool operator>(const T& v, const optional& x);
bool(x) ? *x < v : true.template constexpr bool operator>=(const optional& x, const T& v);
!(x < v).template constexpr bool operator>=(const T& v, const optional& x);
!(v < x).template void swap(optional& x, optional& y) noexcept(noexcept(x.swap(y)));
x.swap(y).template constexpr optional> make_optional(T&& v);
optional>(std::forward(v)) .template struct hash>;
hash shall meet the requirements of class template hash (hash> shall meet the requirements of class template hash.
For an object o of type optional, if bool(o) == true,
hash>()(o) shall evaluate to the same value as hash()(*o) ;
otherwise it evaluates to an unspecified value.anyThis section describes components that C++ programs may use to perform operations on objects of a discriminated type.
5 is held strictly as an int and is not implicitly convertible either to "5" or to 5.0.
This indifference to interpretation but awareness of type
effectively allows safe, generic containers of single values, with no
scope for surprises from ambiguous conversions.
— end note ]
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
class bad_any_cast : public bad_cast
{
public:
virtual const char* what() const noexcept;
};
class any
{
public:
// 6.3.1, any construct/destruct
any() noexcept;
any(const any& other);
any(any&& other) noexcept;
template
any(ValueType&& value);
~any();
// 6.3.2, any assignments
any& operator=(const any& rhs);
any& operator=(any&& rhs) noexcept;
template
any& operator=(ValueType&& rhs);
// 6.3.3, any modifiers
void clear() noexcept;
void swap(any& rhs) noexcept;
// 6.3.4, any observers
bool empty() const noexcept;
const type_info& type() const noexcept;
};
// 6.4, Non-member functions
void swap(any& x, any& y) noexcept;
template
ValueType any_cast(const any& operand);
template
ValueType any_cast(any& operand);
template
ValueType any_cast(any&& operand);
template
const ValueType* any_cast(const any* operand) noexcept;
template
ValueType* any_cast(any* operand) noexcept;
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
bad_any_cast
Objects of type bad_any_cast are thrown by a failed any_cast.
any
An object of class any stores an instance of any type that satisfies the constructor requirements or is empty,
and this is referred to as the state of the class any object.
The stored instance is called the contained object.
Two states are equivalent if they are either both empty or if both
are not empty and if the contained objects are equivalent.
The non-member any_cast functions provide type-safe access to the contained object.
Implementations should avoid the use of dynamically allocated memory for a small contained object.
T for which
is_nothrow_move_constructible_v is true.
any construct/destructany() noexcept;
this->empty().any(const any& other);
any with an equivalent state as other.any(any&& other) noexcept;
any with a state equivalent to the original state of other.other is left in a valid but otherwise unspecified state.template
any(ValueType&& value);
Let T be equal to decay_t.
T shall satisfy the CopyConstructible requirements.
If is_copy_constructible_v is false, the program is ill-formed.any that contains an object of type T direct-initialized with std::forward(value) .decay_t is the same type as any.T.~any();
clear().any assignmentsany& operator=(const any& rhs);
any(rhs).swap(*this).
No effects if an exception is thrown.*this.any& operator=(any&& rhs) noexcept;
any(std::move(rhs)).swap(*this).*this.*this is equivalent to the original state of rhs
and rhs is left in a valid but otherwise unspecified state.template
any& operator=(ValueType&& rhs);
Let T be equal to decay_t.
T shall satisfy the CopyConstructible requirements.
If is_copy_constructible_v is false, the program is ill-formed.tmp of type any that contains an object of type T direct-initialized with std::forward(rhs) , and tmp.swap(*this).
No effects if an exception is thrown.*this.decay_t is the same type as any.T.any modifiersvoid clear() noexcept;
empty() == true.void swap(any& rhs) noexcept;
*this and rhs.any observersbool empty() const noexcept;
true if *this has no contained object, otherwise false.const type_info& type() const noexcept;
*this has a contained object of type T, typeid(T);
otherwise typeid(void).void swap(any& x, any& y) noexcept;
x.swap(y).template
ValueType any_cast(const any& operand); template
ValueType any_cast(any& operand); template
ValueType any_cast(any&& operand);
is_reference_v is true or is_copy_constructible_v is true.
Otherwise the program is ill-formed.*any_cast>>(&operand) .
For the second and third forms, *any_cast>(&operand) .bad_any_cast if operand.type() != typeid(remove_reference_t) .any x(5); // x holds int
assert(any_cast(x) == 5); // cast to value
any_cast(x) = 10; // cast to reference
assert(any_cast(x) == 10);
x = "Meow"; // x holds const char*
assert(strcmp(any_cast(x), "Meow") == 0);
any_cast(x) = "Harry";
assert(strcmp(any_cast(x), "Harry") == 0);
x = string("Meow"); // x holds string
string s, s2("Jane");
s = move(any_cast(x)); // move from any
assert(s == "Meow");
any_cast(x) = move(s2); // move to any
assert(any_cast(x) == "Jane");
string cat("Meow");
const any y(cat); // const y holds string
assert(any_cast(y) == cat);
any_cast(y); // error; cannot
// any_cast away const
— end example ]
template
const ValueType* any_cast(const any* operand) noexcept; template
ValueType* any_cast(any* operand) noexcept;
operand != nullptr && operand->type() == typeid(ValueType),
a pointer to the object contained by operand,
otherwise nullptr.bool is_string(const any& operand) {
return any_cast(&operand) != nullptr;
}
— end example ]
string_view
The class template basic_string_view describes an object that can refer to a constant contiguous sequence of char-like (basic_string_view object is designated by charT.
const charT* and std::basic_string to std::basic_string_view so that user code can accept just std::basic_string_view as a non-templated parameter wherever a sequence of characters is expected.
User-defined types should define their own implicit conversions to std::basic_string_view in order to interoperate with these functions.
— end note ]
The complexity of basic_string_view member functions is O(1) unless otherwise specified.
synopsisnamespace std {
namespace experimental {
inline namespace fundamentals_v2 {
// 7.2, Class template basic_string_view
template>
class basic_string_view;
// 7.9, basic_string_view non-member comparison functions
template
constexpr bool operator==(basic_string_view x,
basic_string_view y) noexcept;
template
constexpr bool operator!=(basic_string_view x,
basic_string_view y) noexcept;
template
constexpr bool operator< (basic_string_view x,
basic_string_view y) noexcept;
template
constexpr bool operator> (basic_string_view x,
basic_string_view y) noexcept;
template
constexpr bool operator<=(basic_string_view x,
basic_string_view y) noexcept;
template
constexpr bool operator>=(basic_string_view x,
basic_string_view y) noexcept;
// see below, sufficient additional overloads of comparison functions
// 7.10, Inserters and extractors
template
basic_ostream&
operator<<(basic_ostream& os,
basic_string_view str);
// basic_string_view typedef names
typedef basic_string_view string_view;
typedef basic_string_view u16string_view;
typedef basic_string_view u32string_view;
typedef basic_string_view wstring_view;
} // namespace fundamentals_v2
} // namespace experimental
// 7.11, Hash support
template struct hash;
template <> struct hash;
template <> struct hash;
template <> struct hash;
template <> struct hash;
} // namespace std
The function templates defined in is included.
basic_string_viewtemplate>
class basic_string_view {
public:
// types
typedef traits traits_type;
typedef charT value_type;
typedef charT* pointer;
typedef const charT* const_pointer;
typedef charT& reference;
typedef const charT& const_reference;
typedef implementation-defined const_iterator; // See 7.4
typedef const_iterator iterator;1
typedef reverse_iterator const_reverse_iterator;
typedef const_reverse_iterator reverse_iterator;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
static constexpr size_type npos = size_type(-1);
// 7.3, basic_string_view constructors and assignment operators
constexpr basic_string_view() noexcept;
constexpr basic_string_view(const basic_string_view&) noexcept = default;
basic_string_view& operator=(const basic_string_view&) noexcept = default;
template
basic_string_view(const basic_string& str) noexcept;
constexpr basic_string_view(const charT* str);
constexpr basic_string_view(const charT* str, size_type len);
// 7.4, basic_string_view iterator support
constexpr const_iterator begin() const noexcept;
constexpr const_iterator end() const noexcept;
constexpr const_iterator cbegin() const noexcept;
constexpr const_iterator cend() const noexcept;
const_reverse_iterator rbegin() const noexcept;
const_reverse_iterator rend() const noexcept;
const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;
// 7.5, basic_string_view capacity
constexpr size_type size() const noexcept;
constexpr size_type length() const noexcept;
constexpr size_type max_size() const noexcept;
constexpr bool empty() const noexcept;
// 7.6, basic_string_view element access
constexpr const_reference operator[](size_type pos) const;
constexpr const_reference at(size_type pos) const;
constexpr const_reference front() const;
constexpr const_reference back() const;
constexpr const_pointer data() const noexcept;
// 7.7, basic_string_view modifiers
constexpr void remove_prefix(size_type n);
constexpr void remove_suffix(size_type n);
constexpr void swap(basic_string_view& s) noexcept;
// 7.8, basic_string_view string operations
template
explicit operator basic_string() const;
template >
basic_string to_string(
const Allocator& a = Allocator()) const;
size_type copy(charT* s, size_type n, size_type pos = 0) const;
constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const;
constexpr int compare(basic_string_view s) const noexcept;
constexpr int compare(size_type pos1, size_type n1, basic_string_view s) const;
constexpr int compare(size_type pos1, size_type n1,
basic_string_view s, size_type pos2, size_type n2) const;
constexpr int compare(const charT* s) const;
constexpr int compare(size_type pos1, size_type n1, const charT* s) const;
constexpr int compare(size_type pos1, size_type n1,
const charT* s, size_type n2) const;
constexpr size_type find(basic_string_view s, size_type pos = 0) const noexcept;
constexpr size_type find(charT c, size_type pos = 0) const noexcept;
constexpr size_type find(const charT* s, size_type pos, size_type n) const;
constexpr size_type find(const charT* s, size_type pos = 0) const;
constexpr size_type rfind(basic_string_view s, size_type pos = npos) const noexcept;
constexpr size_type rfind(charT c, size_type pos = npos) const noexcept;
constexpr size_type rfind(const charT* s, size_type pos, size_type n) const;
constexpr size_type rfind(const charT* s, size_type pos = npos) const;
constexpr size_type find_first_of(basic_string_view s, size_type pos = 0) const noexcept;
constexpr size_type find_first_of(charT c, size_type pos = 0) const noexcept;
constexpr size_type find_first_of(const charT* s, size_type pos, size_type n) const;
constexpr size_type find_first_of(const charT* s, size_type pos = 0) const;
constexpr size_type find_last_of(basic_string_view s, size_type pos = npos) const noexcept;
constexpr size_type find_last_of(charT c, size_type pos = npos) const noexcept;
constexpr size_type find_last_of(const charT* s, size_type pos, size_type n) const;
constexpr size_type find_last_of(const charT* s, size_type pos = npos) const;
constexpr size_type find_first_not_of(basic_string_view s, size_type pos = 0) const noexcept;
constexpr size_type find_first_not_of(charT c, size_type pos = 0) const noexcept;
constexpr size_type find_first_not_of(const charT* s, size_type pos, size_type n) const;
constexpr size_type find_first_not_of(const charT* s, size_type pos = 0) const;
constexpr size_type find_last_not_of(basic_string_view s, size_type pos = npos) const noexcept;
constexpr size_type find_last_not_of(charT c, size_type pos = npos) const noexcept;
constexpr size_type find_last_not_of(const charT* s, size_type pos, size_type n) const;
constexpr size_type find_last_not_of(const charT* s, size_type pos = npos) const;
private:
const_pointer data_; // exposition only
size_type size_; // exposition only
};
In every specialization basic_string_view, the type traits shall satisfy the character traits requirements (traits::char_type shall name the same type as charT.
basic_string_view constructors and assignment operatorsconstexpr basic_string_view() noexcept;
basic_string_view.size_ == 0 and data_ == nullptr.template
basic_string_view(const basic_string& str) noexcept;
basic_string_view, with the postconditions in | Element | Value |
|---|---|
data_ | str.data() |
size_ | str.size() |
constexpr basic_string_view(const charT* str);
str, str + traits::length(str))basic_string_view, with the postconditions
in | Element | Value |
|---|---|
data_ | str |
size_ | traits::length(str) |
traits::length(str))constexpr basic_string_view(const charT* str, size_type len);
str, str + len)basic_string_view, with the postconditions in | Element | Value |
|---|---|
data_ | str |
size_ | len |
basic_string_view iterator supporttypedef implementation-defined const_iterator;
A constant random-access iterator type such that, for a const_iterator it, if &*(it+N) is valid, then it is equal to (&*it)+N.
For a basic_string_view str, any operation that invalidates a pointer in the range str.data(), str.data()+str.size())str's methods.
All requirements on container iterators (basic_string_view::const_iterator as well.
constexpr const_iterator begin() const noexcept; constexpr const_iterator cbegin() const noexcept;
&*begin() == data_ if !empty(),
or else an unspecified value such that begin(), end())constexpr const_iterator end() const noexcept; constexpr const_iterator cend() const noexcept;
begin() + size().const_reverse_iterator rbegin() const noexcept; const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator(end()).const_reverse_iterator rend() const noexcept; const_reverse_iterator crend() const noexcept;
const_reverse_iterator(begin()).basic_string_view capacityconstexpr size_type size() const noexcept;
size_.constexpr size_type length() const noexcept;
size_.constexpr size_type max_size() const noexcept;
basic_string_view.constexpr bool empty() const noexcept;
size_ == 0.basic_string_view element accessconstexpr const_reference operator[](size_type pos) const;
pos < size().data_[pos].basic_string::operator[],
basic_string_view::operator[](size()) has undefined behavior instead of returning charT().
— end note ]
constexpr const_reference at(size_type pos) const;
out_of_range if pos >= size().data_[pos].constexpr const_reference front() const;
!empty()data_[0].constexpr const_reference back() const;
!empty()data_[size() - 1].constexpr const_pointer data() const noexcept;
data_.basic_string::data() and string literals,
data() may return a pointer to a buffer that is not null-terminated.
Therefore it is typically a mistake to pass data() to a routine that takes just a const charT* and expects a null-terminated string.
— end note ]
basic_string_view modifiersconstexpr void remove_prefix(size_type n);
n <= size().data_ += n; size_ -= n;constexpr void remove_suffix(size_type n);
n <= size().size_ -= n;constexpr void swap(basic_string_view& s) noexcept;
*this and s.basic_string_view string operationstemplate
explicit2 operator basic_string<
charT, traits, Allocator>() const;
return basic_string(begin(), end()); size())to_string(allocator).
— end note ]
template>
basic_string to_string(
const Allocator& a = Allocator()) const;
basic_string(begin(), end(), a) .size())size_type copy(charT* s, size_type n, size_type pos = 0) const;
Let rlen be the smaller of n and size() - pos.
out_of_range if pos > size().s, s + rlen)std::copy_n(begin() + pos, rlen, s).rlen.rlen)constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const;
out_of_range if pos > size().rlen of the string to reference as the smaller of n and size() - pos.basic_string_view(data()+pos, rlen).constexpr int compare(basic_string_view str) const noexcept;
rlen of the strings to compare as the smaller of size() and str.size().
The function then compares the two strings by calling traits::compare(data(), str.data(), rlen).rlen)| Condition | Return Value |
|---|---|
size() < str.size() | < 0 |
size() == str.size() | 0 |
size() > str.size() | > 0 |
constexpr int compare(size_type pos1, size_type n1, basic_string_view str) const;
return substr(pos1, n1).compare(str);constexpr int compare(size_type pos1, size_type n1, basic_string_view str,
size_type pos2, size_type n2) const;
return substr(pos1, n1).compare(str.substr(pos2, n2));constexpr int compare(const charT* s) const;
return compare(basic_string_view(s));constexpr int compare(size_type pos1, size_type n1, const charT* s) const;
return substr(pos1, n1).compare(basic_string_view(s));constexpr int compare(size_type pos1, size_type n1,
const charT* s, size_type n2) const;
return substr(pos1, n1).compare(basic_string_view(s, n2));basic_string_viewThis section specifies the basic_string_view member functions named
find, rfind, find_first_of, find_last_of, find_first_not_of, and find_last_not_of.
Member functions in this section have complexity O(size() * str.size()) at worst,
although implementations are encouraged to do better.
Each member function of the form
constexpr return-type fx1(const charT* s, size_type pos);
is equivalent to return fx1(basic_string_view(s), pos);
Each member function of the form
constexpr return-type fx1(const charT* s, size_type pos, size_type n);
is equivalent to return fx1(basic_string_view(s, n), pos);
Each member function of the form
constexpr return-type fx2(charT c, size_type pos);
is equivalent to return fx2(basic_string_view(&c, 1), pos);
constexpr size_type find(basic_string_view str, size_type pos = 0) const noexcept;
xpos, if possible, such that the following conditions obtain:
pos <= xposxpos + str.size() <= size()traits::eq(at(xpos+I), str.at(I)) for all elements I of the string referenced by str.xpos if the function can determine such a value for xpos.
Otherwise, returns npos.traits::eq().constexpr size_type rfind(basic_string_view str, size_type pos = npos) const noexcept;
xpos, if possible, such that the following conditions obtain:
xpos <= posxpos + str.size() <= size()traits::eq(at(xpos+I), str.at(I)) for all elements I of the string referenced by str.xpos if the function can determine such a value for xpos.
Otherwise, returns npos.traits::eq().constexpr size_type find_first_of(basic_string_view str, size_type pos = 0) const noexcept;
xpos, if possible, such that the following conditions obtain:
pos <= xposxpos < size()traits::eq(at(xpos), str.at(I)) for some element I of the string referenced by str.xpos if the function can determine such a value for xpos.
Otherwise, returns npos.traits::eq().constexpr size_type find_last_of(basic_string_view str, size_type pos = npos) const noexcept;
xpos, if possible, such that the following conditions obtain:
xpos <= posxpos < size()traits::eq(at(xpos), str.at(I)) for some element I of the string referenced by str.xpos if the function can determine such a value for xpos.
Otherwise, returns npos.traits::eq().constexpr size_type find_first_not_of(basic_string_view str, size_type pos = 0) const noexcept;
xpos, if possible, such that the following conditions obtain:
pos <= xposxpos < size()traits::eq(at(xpos), str.at(I)) for no element I of the string referenced by str.xpos if the function can determine such a value for xpos. Otherwise, returns npos.traits::eq().constexpr size_type find_last_not_of(basic_string_view str, size_type pos = npos) const noexcept;
xpos, if possible, such that the following conditions obtain:
xpos <= posxpos < size()traits::eq(at(xpos), str.at(I)) for no element I of the string referenced by str.xpos if the function can determine such a value for xpos.
Otherwise, returns npos.traits::eq().basic_string_view non-member comparison functions
Let S be basic_string_view, and sv be an instance of S.
Implementations shall provide sufficient additional overloads marked constexpr and noexcept
so that an object t with an implicit conversion to S can be compared according to
| Expression | Equivalent to |
|---|---|
t == sv | S(t) == sv |
sv == t | sv == S(t) |
t != sv | S(t) != sv |
sv != t | sv != S(t) |
t < sv | S(t) < sv |
sv < t | sv < S(t) |
t > sv | S(t) > sv |
sv > t | sv > S(t) |
t <= sv | S(t) <= sv |
sv <= t | sv <= S(t) |
t >= sv | S(t) >= sv |
sv >= t | sv >= S(t) |
template using __identity = decay_t;
template
constexpr bool operator==(
basic_string_view lhs,
basic_string_view rhs) noexcept {
return lhs.compare(rhs) == 0;
}
template
constexpr bool operator==(
basic_string_view lhs,
__identity> rhs) noexcept {
return lhs.compare(rhs) == 0;
}
template
constexpr bool operator==(
__identity> lhs,
basic_string_view rhs) noexcept {
return lhs.compare(rhs) == 0;
}
— end example ]
template
constexpr bool operator==(basic_string_view lhs,
basic_string_view rhs) noexcept;
lhs.compare(rhs) == 0.template
constexpr bool operator!=(basic_string_view lhs,
basic_string_view rhs) noexcept;
lhs.compare(rhs) != 0.template
constexpr bool operator< (basic_string_view lhs,
basic_string_view rhs) noexcept;
lhs.compare(rhs) < 0.template
constexpr bool operator> (basic_string_view lhs,
basic_string_view rhs) noexcept;
lhs.compare(rhs) > 0.template
constexpr bool operator<=(basic_string_view lhs,
basic_string_view rhs) noexcept;
lhs.compare(rhs) <= 0.template
constexpr bool operator>=(basic_string_view lhs,
basic_string_view rhs) noexcept;
lhs.compare(rhs) >= 0.template
basic_ostream&
operator<<(basic_ostream& os,
basic_string_view str);
return os << str.to_string();template <> struct hash; template <> struct hash; template <> struct hash; template <> struct hash;
The template specializations shall meet the requirements of class template hash (
#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
// See C++14 §20.7.7 , uses_allocator
template constexpr bool uses_allocator_v
= uses_allocator::value;
// 8.2.1, Class template shared_ptr
template class shared_ptr;
// C++14 §20.8.2.2.6
template shared_ptr make_shared(Args&&... args);
template
shared_ptr allocate_shared(const A& a, Args&&... args);
// C++14 §20.8.2.2.7
template
bool operator==(const shared_ptr& a, const shared_ptr& b) noexcept;
template
bool operator!=(const shared_ptr& a, const shared_ptr& b) noexcept;
template
bool operator<(const shared_ptr& a, const shared_ptr& b) noexcept;
template
bool operator>(const shared_ptr& a, const shared_ptr& b) noexcept;
template
bool operator<=(const shared_ptr& a, const shared_ptr& b) noexcept;
template
bool operator>=(const shared_ptr& a, const shared_ptr& b) noexcept;
template
bool operator==(const shared_ptr& a, nullptr_t) noexcept;
template
bool operator==(nullptr_t, const shared_ptr& b) noexcept;
template
bool operator!=(const shared_ptr& a, nullptr_t) noexcept;
template
bool operator!=(nullptr_t, const shared_ptr& b) noexcept;
template
bool operator<(const shared_ptr& a, nullptr_t) noexcept;
template
bool operator<(nullptr_t, const shared_ptr& b) noexcept;
template
bool operator<=(const shared_ptr& a, nullptr_t) noexcept;
template
bool operator<=(nullptr_t, const shared_ptr& b) noexcept;
template
bool operator>(const shared_ptr& a, nullptr_t) noexcept;
template
bool operator>(nullptr_t, const shared_ptr& b) noexcept;
template
bool operator>=(const shared_ptr& a, nullptr_t) noexcept;
template
bool operator>=(nullptr_t, const shared_ptr& b) noexcept;
// C++14 §20.8.2.2.8
template void swap(shared_ptr& a, shared_ptr& b) noexcept;
// 8.2.1.3, shared_ptr casts
template
shared_ptr static_pointer_cast(const shared_ptr& r) noexcept;
template
shared_ptr dynamic_pointer_cast(const shared_ptr& r) noexcept;
template
shared_ptr const_pointer_cast(const shared_ptr& r) noexcept;
template
shared_ptr reinterpret_pointer_cast(const shared_ptr& r) noexcept;
// C++14 §20.8.2.2.10
template D* get_deleter(const shared_ptr& p) noexcept;
// C++14 §20.8.2.2.11
template
basic_ostream& operator<< (basic_ostream& os, const shared_ptr& p);
// C++14 §20.8.2.3
template class weak_ptr;
// C++14 §20.8.2.3.6
template void swap(weak_ptr& a, weak_ptr& b) noexcept;
// C++14 §20.8.2.4
template class owner_less;
// C++14 §20.8.2.5
template class enable_shared_from_this;
// C++14 §20.8.2.6
template
bool atomic_is_lock_free(const shared_ptr* p);
template
shared_ptr atomic_load(const shared_ptr* p);
template
shared_ptr atomic_load_explicit(const shared_ptr* p, memory_order mo);
template
void atomic_store(shared_ptr* p, shared_ptr r);
template
void atomic_store_explicit(shared_ptr* p, shared_ptr r, memory_order mo);
template
shared_ptr atomic_exchange(shared_ptr* p, shared_ptr r);
template
shared_ptr atomic_exchange_explicit(shared_ptr* p, shared_ptr r,
memory_order mo);
template
bool atomic_compare_exchange_weak(
shared_ptr* p, shared_ptr* v, shared_ptr w);
template
bool atomic_compare_exchange_strong(
shared_ptr* p, shared_ptr* v, shared_ptr w);
template
bool atomic_compare_exchange_weak_explicit(
shared_ptr* p, shared_ptr* v, shared_ptr w,
memory_order success, memory_order failure);
template
bool atomic_compare_exchange_strong_explicit(
shared_ptr* p, shared_ptr* v, shared_ptr w,
memory_order success, memory_order failure);
// 8.12, Non-owning pointers
template class observer_ptr;
// 8.12.6, observer_ptr specialized algorithms
template
void swap(observer_ptr&, observer_ptr&) noexcept;
template
observer_ptr make_observer(W*) noexcept;
// (in)equality operators
template
bool operator==(observer_ptr, observer_ptr);
template
bool operator!=(observer_ptr, observer_ptr);
template
bool operator==(observer_ptr, nullptr_t) noexcept;
template
bool operator!=(observer_ptr, nullptr_t) noexcept;
template
bool operator==(nullptr_t, observer_ptr) noexcept;
template
bool operator!=(nullptr_t, observer_ptr) noexcept;
// ordering operators
template
bool operator<(observer_ptr, observer_ptr);
template
bool operator>(observer_ptr, observer_ptr);
template
bool operator<=(observer_ptr, observer_ptr);
template
bool operator>=(observer_ptr, observer_ptr);
} // inline namespace fundamentals_v2
} // namespace experimental
// C++14 §20.8.2.7
template struct hash>;
// 8.12.7, observer_ptr hash support
template struct hash;
template struct hash>;
} // namespace std
The specification of all declarations within this sub-clause
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
template class shared_ptr {
public:
typedef typename remove_extent_t element_type;
// 8.2.1.1, shared_ptr constructors
constexpr shared_ptr() noexcept;
template explicit shared_ptr(Y* p);
template shared_ptr(Y* p, D d);
template shared_ptr(Y* p, D d, A a);
template shared_ptr(nullptr_t p, D d)
template shared_ptr(nullptr_t p, D d, A a);
template shared_ptr(const shared_ptr& r, element_type* p) noexcept;
shared_ptr(const shared_ptr& r) noexcept;
template shared_ptr(const shared_ptr& r) noexcept;
shared_ptr(shared_ptr&& r) noexcept;
template shared_ptr(shared_ptr&& r) noexcept;
template explicit shared_ptr(const weak_ptr& r);
template shared_ptr(auto_ptr&& r);
template shared_ptr(unique_ptr&& r);
constexpr shared_ptr(nullptr_t) : shared_ptr() { }
// C++14 §20.8.2.2.2
~shared_ptr();
// C++14 §20.8.2.2.3
shared_ptr& operator=(const shared_ptr& r) noexcept;
template shared_ptr& operator=(const shared_ptr& r) noexcept;
shared_ptr& operator=(shared_ptr&& r) noexcept;
template shared_ptr& operator=(shared_ptr&& r) noexcept;
template shared_ptr& operator=(auto_ptr&& r);
template shared_ptr& operator=(unique_ptr&& r);
// C++14 §20.8.2.2.4
void swap(shared_ptr& r) noexcept;
void reset() noexcept;
template void reset(Y* p);
template void reset(Y* p, D d);
template void reset(Y* p, D d, A a);
// 8.2.1.2, shared_ptr observers
element_type* get() const noexcept;
T& operator*() const noexcept;
T* operator->() const noexcept;
element_type& operator[](ptrdiff_t i) const noexcept;
long use_count() const noexcept;
bool unique() const noexcept;
explicit operator bool() const noexcept;
template bool owner_before(shared_ptr const& b) const;
template bool owner_before(weak_ptr const& b) const;
};
// C++14 §20.8.2.2.6
template shared_ptr make_shared(Args&&... args);
template
shared_ptr allocate_shared(const A& a, Args&&... args);
// C++14 §20.8.2.2.7
template
bool operator==(const shared_ptr& a, const shared_ptr& b) noexcept;
template
bool operator!=(const shared_ptr& a, const shared_ptr& b) noexcept;
template
bool operator<(const shared_ptr& a, const shared_ptr& b) noexcept;
template
bool operator>(const shared_ptr& a, const shared_ptr& b) noexcept;
template
bool operator<=(const shared_ptr& a, const shared_ptr& b) noexcept;
template
bool operator>=(const shared_ptr& a, const shared_ptr& b) noexcept;
template
bool operator==(const shared_ptr& a, nullptr_t) noexcept;
template
bool operator==(nullptr_t, const shared_ptr& b) noexcept;
template
bool operator!=(const shared_ptr& a, nullptr_t) noexcept;
template
bool operator!=(nullptr_t, const shared_ptr& b) noexcept;
template
bool operator<(const shared_ptr& a, nullptr_t) noexcept;
template
bool operator<(nullptr_t, const shared_ptr& b) noexcept;
template
bool operator<=(const shared_ptr& a, nullptr_t) noexcept;
template
bool operator<=(nullptr_t, const shared_ptr& b) noexcept;
template
bool operator>(const shared_ptr& a, nullptr_t) noexcept;
template
bool operator>(nullptr_t, const shared_ptr& b) noexcept;
template
bool operator>=(const shared_ptr& a, nullptr_t) noexcept;
template
bool operator>=(nullptr_t, const shared_ptr& b) noexcept;
// C++14 §20.8.2.2.8
template void swap(shared_ptr& a, shared_ptr& b) noexcept;
// 8.2.1.3, shared_ptr casts
template
shared_ptr static_pointer_cast(const shared_ptr& r) noexcept;
template
shared_ptr dynamic_pointer_cast(const shared_ptr& r) noexcept;
template
shared_ptr const_pointer_cast(const shared_ptr& r) noexcept;
template
shared_ptr reinterpret_pointer_cast(const shared_ptr& r) noexcept;
// C++14 §20.8.2.2.10
template D* get_deleter(const shared_ptr& p) noexcept;
// C++14 §20.8.2.2.11
template
basic_ostream& operator<< (basic_ostream& os, const shared_ptr& p);
// C++14 §20.8.2.4
template class owner_less;
// C++14 §20.8.2.5
template class enable_shared_from_this;
// C++14 §20.8.2.6
template
bool atomic_is_lock_free(const shared_ptr* p);
template
shared_ptr atomic_load(const shared_ptr* p);
template
shared_ptr atomic_load_explicit(const shared_ptr* p, memory_order mo);
template
void atomic_store(shared_ptr* p, shared_ptr r);
template
void atomic_store_explicit(shared_ptr* p, shared_ptr r, memory_order mo);
template
shared_ptr atomic_exchange(shared_ptr* p, shared_ptr r);
template
shared_ptr atomic_exchange_explicit(shared_ptr* p, shared_ptr r,
memory_order mo);
template
bool atomic_compare_exchange_weak(
shared_ptr* p, shared_ptr* v, shared_ptr w);
template
bool atomic_compare_exchange_strong(
shared_ptr* p, shared_ptr* v, shared_ptr w);
template
bool atomic_compare_exchange_weak_explicit(
shared_ptr* p, shared_ptr* v, shared_ptr w,
memory_order success, memory_order failure);
template
bool atomic_compare_exchange_strong_explicit(
shared_ptr* p, shared_ptr* v, shared_ptr w,
memory_order success, memory_order failure);
} // namespace fundamentals_v2
} // namespace experimental
// C++14 §20.8.2.7
template struct hash>;
} // namespace std
shared_ptr constructorstemplate explicit shared_ptr(Y* p);
Y shall be a complete type.
The expression delete[] p, when T is an array type,
or delete p, when T is not an array type,
shall be well-formed, shall have well defined behavior, and shall not throw exceptions.
When T is U[N], Y(*)[N] shall be convertible to T*;
when T is U[], Y(*)[] shall be convertible to T*;
otherwise, Y* shall be convertible to T*.T is not an array type, constructs a shared_ptr object that owns the pointer p.
Otherwise, constructs a shared_ptr that owns p and a deleter of an unspecified type that calls delete[] p.use_count() == 1 && get() == p.bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.delete p is called when T is not an array type, delete[] p otherwise.template shared_ptr(Y* p, D d); template shared_ptr(Y* p, D d, A a); template shared_ptr(nullptr_t p, D d); template shared_ptr(nullptr_t p, D d, A a);
D shall be CopyConstructible. The copy constructor and destructor of D shall not throw exceptions. The expression d(p) shall be well formed, shall have well defined behavior, and shall not throw exceptions. A shall be an allocator (A shall not throw exceptions.
When T is U[N], Y(*)[N] shall be convertible to T*;
when T is U[], Y(*)[] shall be convertible to T*;
otherwise, Y* shall be convertible to T*.shared_ptr object that owns the object p and the deleter d. The second and fourth constructors shall use a copy of a to allocate memory for internal use.use_count() == 1 && get() == p.bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.d(p) is called.template shared_ptr(const shared_ptr& r, element_type* p) noexcept;
shared_ptr instance that stores p and shares ownership with r.get() == p && use_count() == r.use_count().shared_ptr(const shared_ptr& r) noexcept; template shared_ptr(const shared_ptr& r) noexcept;
Y* is compatible with T*.r is empty, constructs an empty shared_ptr object; otherwise, constructs a shared_ptr object that shares ownership with r.get() == r.get() && use_count() == r.use_count().shared_ptr(shared_ptr&& r) noexcept; template shared_ptr(shared_ptr&& r) noexcept;
Y* is compatible with T*.shared_ptr instance from r.*this shall contain the old value of r. r shall be empty. r.get() == 0.template explicit shared_ptr(const weak_ptr& r);
Y* shall be compatible with T*.shared_ptr object that shares ownership with r and stores a copy of the pointer stored in r.use_count() == r.use_count().bad_weak_ptr when r.expired().template shared_ptr(unique_ptr&& r);
Y* is compatible with T*.shared_ptr(r.release(), r.get_deleter()) when D is not a reference type, otherwise shared_ptr(r.release(), ref(r.get_deleter())).shared_ptr observerselement_type* get() const noexcept;
T& operator*() const noexcept;
get() != 0.*get().T is an array type or (possibly cv-qualified) void,
it is unspecified whether this member function is declared. If it is
declared, it is unspecified what its return type is, except that the
declaration (although not necessarily the definition) of the function
shall be well formed.T* operator->() const noexcept;
get() != 0.get().T is an array type, it is
unspecified whether this member function is declared.
If it is declared, it is unspecified what its return type is,
except that the declaration (although not necessarily the definition) of
the function shall be well formed.element_type& operator[](ptrdiff_t i) const noexcept;
get() != 0 && i >= 0. If T is U[N], i < N.get()[i].T is not an array type, it is
unspecified whether this member function is declared.
If it is declared, it is unspecified what its return type is,
except that the declaration (although not necessarily the definition) of
the function shall be well formed.shared_ptr caststemplate shared_ptr static_pointer_cast(const shared_ptr& r) noexcept;
static_cast((U*)0) shall be well formed.shared_ptr(r, static_cast::element_type*>(r.get())) .template shared_ptr dynamic_pointer_cast(const shared_ptr& r) noexcept;
dynamic_cast((U*)0) shall be well formed.dynamic_cast::element_type*>(r.get()) returns a nonzero value p, shared_ptr(r, p) ;shared_ptr() .template shared_ptr const_pointer_cast(const shared_ptr& r) noexcept;
const_cast((U*)0) shall be well formed.shared_ptr(r, const_cast::element_type*>(r.get())) .template shared_ptr reinterpret_pointer_cast(const shared_ptr& r) noexcept;
reinterpret_cast((U*)0) shall be well formed.shared_ptr(r, reinterpret_cast::element_type*>(r.get())) .
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
template class weak_ptr {
public:
typedef typename remove_extent_t element_type;
// 8.2.2.1, weak_ptr constructors
constexpr weak_ptr() noexcept;
template weak_ptr(shared_ptr const& r) noexcept;
weak_ptr(weak_ptr const& r) noexcept;
template weak_ptr(weak_ptr const& r) noexcept;
weak_ptr(weak_ptr&& r) noexcept;
template weak_ptr(weak_ptr&& r) noexcept;
// C++14 §20.8.2.3.2
~weak_ptr();
// C++14 §20.8.2.3.3
weak_ptr& operator=(weak_ptr const& r) noexcept;
template weak_ptr& operator=(weak_ptr const& r) noexcept;
template weak_ptr& operator=(shared_ptr const& r) noexcept;
weak_ptr& operator=(weak_ptr&& r) noexcept;
template weak_ptr& operator=(weak_ptr&& r) noexcept;
// C++14 §20.8.2.3.4
void swap(weak_ptr& r) noexcept;
void reset() noexcept;
// C++14 §20.8.2.3.5
long use_count() const noexcept;
bool expired() const noexcept;
shared_ptr lock() const noexcept;
template bool owner_before(shared_ptr const& b) const;
template bool owner_before(weak_ptr const& b) const;
};
// C++14 §20.8.2.3.6
template void swap(weak_ptr& a, weak_ptr& b) noexcept;
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
weak_ptr constructorsweak_ptr(const weak_ptr& r) noexcept; template weak_ptr(const weak_ptr& r) noexcept; template weak_ptr(const shared_ptr& r) noexcept;
Y* is compatible with T*.r is empty, constructs an empty weak_ptr object; otherwise, constructs a weak_ptr object that shares ownership with r and stores a copy of the pointer stored in r.use_count() == r.use_count().
A type-erased allocator is an allocator or memory resource, alloc,
used to allocate internal data structures for an object X of type C,
but where C is not dependent on the type of alloc.
Once alloc has been supplied to X (typically as a constructor argument),
alloc can be retrieved from X only as a pointer rptr of static type std::experimental::pmr::memory_resource* (rptr is computed from alloc depends on the type of alloc as described in
Additionally, class C shall meet the following requirements:
C::allocator_type shall be identical to std::experimental::erased_type.X.get_memory_resource() returns rptr. synopsisnamespace std {
namespace experimental {
inline namespace fundamentals_v2 {
namespace pmr {
class memory_resource;
bool operator==(const memory_resource& a,
const memory_resource& b) noexcept;
bool operator!=(const memory_resource& a,
const memory_resource& b) noexcept;
template class polymorphic_allocator;
template
bool operator==(const polymorphic_allocator& a,
const polymorphic_allocator& b) noexcept;
template
bool operator!=(const polymorphic_allocator& a,
const polymorphic_allocator& b) noexcept;
// The name resource_adaptor_imp is for exposition only.
template class resource_adaptor_imp;
template
using resource_adaptor = resource_adaptor_imp<
allocator_traits::rebind_alloc>;
// Global memory resources
memory_resource* new_delete_resource() noexcept;
memory_resource* null_memory_resource() noexcept;
// The default memory resource
memory_resource* set_default_resource(memory_resource* r) noexcept;
memory_resource* get_default_resource() noexcept;
// Standard memory resources
struct pool_options;
class synchronized_pool_resource;
class unsynchronized_pool_resource;
class monotonic_buffer_resource;
} // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
memory_resourcememory_resource overview
The memory_resource class is an abstract interface to an unbounded set of classes encapsulating memory resources.
class memory_resource {
// For exposition only
static constexpr size_t max_align = alignof(max_align_t);
public:
virtual ~memory_resource();
void* allocate(size_t bytes, size_t alignment = max_align);
void deallocate(void* p, size_t bytes,
size_t alignment = max_align);
bool is_equal(const memory_resource& other) const noexcept;
protected:
virtual void* do_allocate(size_t bytes, size_t alignment) = 0;
virtual void do_deallocate(void* p, size_t bytes,
size_t alignment) = 0;
virtual bool do_is_equal(const memory_resource& other) const noexcept = 0;
};
memory_resource public member functions~memory_resource();
void* allocate(size_t bytes, size_t alignment = max_align);
return do_allocate(bytes, alignment);void deallocate(void* p, size_t bytes, size_t alignment = max_align);
do_deallocate(p, bytes, alignment);bool is_equal(const memory_resource& other) const noexcept;
return do_is_equal(other);memory_resource protected virtual member functionsvirtual void* do_allocate(size_t bytes, size_t alignment) = 0;
bytes.
The returned storage is aligned to the specified alignment, if such alignment is supported;
otherwise it is aligned to max_align.virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0;
p shall have been returned from a prior call to allocate(bytes, alignment) on a memory resource equal to *this,
and the storage at p shall not yet have been deallocated.virtual bool do_is_equal(const memory_resource& other) const noexcept = 0;
true if memory allocated from this can be deallocated from other and vice-versa;
otherwise it shall return false.
dynamic_cast(&other) and go no further (i.e., return false) if it returns nullptr.
— end note ]
memory_resource equalitybool operator==(const memory_resource& a, const memory_resource& b) noexcept;
&a == &b || a.is_equal(b).bool operator!=(const memory_resource& a, const memory_resource& b) noexcept;
!(a == b).polymorphic_allocatorpolymorphic_allocator overview
A specialization of class template pmr::polymorphic_allocator conforms to the Allocator requirements (pmr::polymorphic_allocator can exhibit entirely different allocation behavior.
This runtime polymorphism allows objects that use polymorphic_allocator to behave as if they used different allocator types at run time even though they use the same static allocator type.
template
class polymorphic_allocator {
memory_resource* m_resource; // For exposition only
public:
typedef Tp value_type;
polymorphic_allocator() noexcept;
polymorphic_allocator(memory_resource* r);
polymorphic_allocator(const polymorphic_allocator& other) = default;
template
polymorphic_allocator(const polymorphic_allocator& other) noexcept;
polymorphic_allocator&
operator=(const polymorphic_allocator& rhs) = default;
Tp* allocate(size_t n);
void deallocate(Tp* p, size_t n);
template
void construct(T* p, Args&&... args);
// Specializations for pair using piecewise construction
template
void construct(pair* p, piecewise_construct_t,
tuple x, tuple y);
template
void construct(pair* p);
template
void construct(pair* p, U&& x, V&& y);
template
void construct(pair* p, const std::pair& pr);
template
void construct(pair* p, pair&& pr);
template
void destroy(T* p);
// Return a default-constructed allocator (no allocator propagation)
polymorphic_allocator select_on_container_copy_construction() const;
memory_resource* resource() const;
};
polymorphic_allocator constructorspolymorphic_allocator() noexcept;
m_resource to get_default_resource().polymorphic_allocator(memory_resource* r);
r is non-null.m_resource to r.memory_resource*.template
polymorphic_allocator(const polymorphic_allocator& other) noexcept;
m_resource to other.resource().polymorphic_allocator member functionsTp* allocate(size_t n);
return static_cast(m_resource->allocate(n * sizeof(Tp), alignof(Tp))); void deallocate(Tp* p, size_t n);
p was allocated from a memory resource, x, equal to *m_resource, using x.allocate(n * sizeof(Tp), alignof(Tp)).m_resource->deallocate(p, n * sizeof(Tp), alignof(Tp)).template
void construct(T* p, Args&&... args);
T
with allocator this->resource() (see std::forward(args)... is well-formed.
T object at p by this->resource() (std::forward(args)... .T throws.template
void construct(pair* p, piecewise_construct_t,
tuple x, tuple y);
xprime be a tuple constructed from x according to the appropriate rule from the following list.
std::pair object at p
as if by separate uses-allocator construction with allocator this->resource() (p->first using the elements of x
and p->second using the elements of y.
— end note ]
uses_allocator_v is false and
is_constructible_v is true, then xprime is x.uses_allocator_v is true and
is_constructible_v is true,
then xprime is tuple_cat(make_tuple(allocator_arg, this->resource()), std::move(x)).uses_allocator_v is true and
is_constructible_v is true,
then xprime is tuple_cat(std::move(x), make_tuple(this->resource())).yprime be a tuple constructed from y
according to the appropriate rule from the following list:
uses_allocator_v is false and
is_constructible_v is true, then yprime is y.uses_allocator_v is true and
is_constructible_v is true, then yprime is tuple_cat(make_tuple(allocator_arg, this->resource()), std::move(y)).uses_allocator_v is true and
is_constructible_v is true, then
yprime is tuple_cat(std::move(y), make_tuple(this->resource())).std::pair object at p using constructor arguments piecewise_construct, xprime, yprime.
template
void construct(std::pair* p);
this->construct(p, piecewise_construct, tuple<>(), tuple<>());template
void construct(std::pair* p, U&& x, V&& y);
this->construct(p, piecewise_construct, forward_as_tuple(std::forward(x)), forward_as_tuple(std::forward(y))); template
void construct(std::pair* p, const std::pair& pr);
this->construct(p, piecewise_construct, forward_as_tuple(pr.first), forward_as_tuple(pr.second));template
void construct(std::pair* p, std::pair&& pr);
this->construct(p, piecewise_construct,
forward_as_tuple(std::forward(pr.first)),
forward_as_tuple(std::forward(pr.second))); template
void destroy(T* p);
p->~T().polymorphic_allocator select_on_container_copy_construction() const;
polymorphic_allocator().memory_resource* resource() const;
m_resource.template
bool operator==(const polymorphic_allocator& a,
const polymorphic_allocator& b) noexcept;
*a.resource() == *b.resource().template
bool operator!=(const polymorphic_allocator& a,
const polymorphic_allocator& b) noexcept;
! (a == b).resource_adaptorresource_adaptor
An instance of resource_adaptor is an adaptor that wraps a memory_resource interface around Allocator.
In order that resource_adaptor and resource_adaptor are the same type for any allocator template X and types T and U,
resource_adaptor is rendered as an alias to a class template such that Allocator is rebound to a char value type in every specialization of the class template.
The requirements on this class template are defined below.
The name resource_adaptor_imp is for exposition only and is not normative,
but the definitions of the members of that class, whatever its name, are normative.
In addition to the Allocator requirements (resource_adaptor shall meet the following additional requirements:
typename allocator_traits::pointer shall be identical to typename allocator_traits::value_type* .typename allocator_traits::const_pointer shall be identical to typename allocator_traits::value_type const* .typename allocator_traits::void_pointer shall be identical to void*.typename allocator_traits::const_void_pointer shall be identical to void const*.
// The name resource_adaptor_imp is for exposition only.
template
class resource_adaptor_imp : public memory_resource {
// for exposition only
Allocator m_alloc;
public:
typedef Allocator allocator_type;
resource_adaptor_imp() = default;
resource_adaptor_imp(const resource_adaptor_imp&) = default;
resource_adaptor_imp(resource_adaptor_imp&&) = default;
explicit resource_adaptor_imp(const Allocator& a2);
explicit resource_adaptor_imp(Allocator&& a2);
resource_adaptor_imp& operator=(const resource_adaptor_imp&) = default;
allocator_type get_allocator() const { return m_alloc; }
protected:
virtual void* do_allocate(size_t bytes, size_t alignment);
virtual void do_deallocate(void* p, size_t bytes, size_t alignment);
virtual bool do_is_equal(const memory_resource& other) const noexcept;
};
template
using resource_adaptor = typename resource_adaptor_imp<
allocator_traits::template rebind_alloc>;
resource_adaptor_imp constructorsexplicit resource_adaptor_imp(const Allocator& a2);
m_alloc with a2.explicit resource_adaptor_imp(Allocator&& a2);
m_alloc with std::move(a2).resource_adaptor_imp member functionsvoid* do_allocate(size_t bytes, size_t alignment);
m_alloc.allocate. The size and alignment of the allocated memory shall meet the requirements for a class derived from memory_resource (void do_deallocate(void* p, size_t bytes, size_t alignment);
p was previously allocated using A.allocate, where A == m_alloc, and not subsequently deallocated.m_alloc.deallocate().bool do_is_equal(const memory_resource& other) const noexcept;
Let p be dynamic_cast.
false if p is null, otherwise the value of m_alloc == p->m_alloc.memory_resource objectsmemory_resource* new_delete_resource() noexcept;
memory_resource that can serve as a resource for allocating memory using ::operator new and ::operator delete. The same value is returned every time this function is called. For return value p and memory resource r, p->is_equal(r) returns &r == p.memory_resource* null_memory_resource() noexcept;
memory_resource
for which allocate() always throws bad_alloc and
for which deallocate() has no effect.
The same value is returned every time this function is called.
For return value p and memory resource r, p->is_equal(r) returns &r == p.
The default memory resource pointer is a pointer to a memory resource
that is used by certain facilities when an explicit memory resource is not supplied through the interface.
Its initial value is the return value of new_delete_resource().
memory_resource* set_default_resource(memory_resource* r) noexcept;
r is non-null, sets the value of the default memory resource pointer to r,
otherwise sets the default memory resource pointer to new_delete_resource().
get_default_resource() == r.set_default_resource and get_default_resource functions shall not incur a data race.
A call to the set_default_resource function shall synchronize with subsequent calls to the set_default_resource and get_default_resource functions.
memory_resource* get_default_resource() noexcept;
synchronized_pool_resource and unsynchronized_pool_resource
The synchronized_pool_resource and unsynchronized_pool_resource classes (collectively, pool resource classes)
are general-purpose memory resources having the following qualities:
deallocate has not been called for some of the allocated blocks.do_allocate.
Each call to do_allocate(size, alignment) is dispatched to the pool serving the smallest blocks accommodating at least size bytes.pool_options struct may be passed to the pool resource constructors to tune the largest block size and the maximum chunk size.
A synchronized_pool_resource may be accessed from multiple threads without external synchronization
and may have thread-specific pools to reduce synchronization costs.
An unsynchronized_pool_resource class may not be accessed from multiple threads simultaneously
and thus avoids the cost of synchronization entirely in single-threaded applications.
struct pool_options {
size_t max_blocks_per_chunk = 0;
size_t largest_required_pool_block = 0;
};
class synchronized_pool_resource : public memory_resource {
public:
synchronized_pool_resource(const pool_options& opts, memory_resource* upstream);
synchronized_pool_resource()
: synchronized_pool_resource(pool_options(), get_default_resource()) { }
explicit synchronized_pool_resource(memory_resource* upstream)
: synchronized_pool_resource(pool_options(), upstream) { }
explicit synchronized_pool_resource(const pool_options& opts)
: synchronized_pool_resource(opts, get_default_resource()) { }
synchronized_pool_resource(
const synchronized_pool_resource&) = delete;
virtual ~synchronized_pool_resource();
synchronized_pool_resource& operator=(
const synchronized_pool_resource&) = delete;
void release();
memory_resource* upstream_resource() const;
pool_options options() const;
protected:
virtual void* do_allocate(size_t bytes, size_t alignment);
virtual void do_deallocate(void* p, size_t bytes, size_t alignment);
virtual bool do_is_equal(const memory_resource& other) const noexcept;
};
class unsynchronized_pool_resource : public memory_resource {
public:
unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream);
unsynchronized_pool_resource()
: unsynchronized_pool_resource(pool_options(), get_default_resource()) { }
explicit unsynchronized_pool_resource(memory_resource* upstream)
: unsynchronized_pool_resource(pool_options(), upstream) { }
explicit unsynchronized_pool_resource(const pool_options& opts)
: unsynchronized_pool_resource(opts, get_default_resource()) { }
unsynchronized_pool_resource(
const unsynchronized_pool_resource&) = delete;
virtual ~unsynchronized_pool_resource();
unsynchronized_pool_resource& operator=(
const unsynchronized_pool_resource&) = delete;
void release();
memory_resource* upstream_resource() const;
pool_options options() const;
protected:
virtual void* do_allocate(size_t bytes, size_t alignment);
virtual void do_deallocate(void* p, size_t bytes, size_t alignment);
virtual bool do_is_equal(const memory_resource& other) const noexcept;
};
pool_options data members
The members of pool_options comprise a set of constructor options for pool resources.
The effect of each option on the pool resource behavior is described below:
size_t max_blocks_per_chunk;
The maximum number of blocks that will be allocated at once from the upstream memory resource to replenish a pool.
If the value of max_blocks_per_chunk is zero or
is greater than an implementation-defined limit, that limit is used
instead.
The implementation may choose to use a smaller value than is
specified in this field and may use different values for different
pools.
size_t largest_required_pool_block;
The largest allocation size that is required to be fulfilled
using the pooling mechanism.
Attempts to allocate a single block larger than this threshold
will be allocated directly from the upstream memory resource.
If largest_required_pool_block is zero or is greater than an implementation-defined limit, that limit is used instead.
The implementation may choose a pass-through threshold larger than specified in this field.
synchronized_pool_resource(const pool_options& opts, memory_resource* upstream); unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream);
upstream is the address of a valid memory resource.upstream whenever the pool resource is unable to satisfy a memory request from its own internal data structures.
The resulting object will hold a copy of upstream, but will not own the resource to which upstream points.
upstream->allocate() will be substantially fewer than calls to this->allocate() in most cases.
— end note ]
upstream->allocate() throws.
It is unspecified if or under what conditions this constructor calls upstream->allocate().virtual ~synchronized_pool_resource(); virtual ~unsynchronized_pool_resource();
this->release().void release();
upstream_resource()->deallocate() as necessary to release all allocated memory.
upstream_resource() even if deallocate has not been called for some of the allocated blocks.
— end note ]
memory_resource* upstream_resource() const;
upstream argument provided to the constructor of this object.pool_options options() const;
virtual void* do_allocate(size_t bytes, size_t alignment);
bytes.
The size and alignment of the allocated memory shall meet the requirements for a class derived from memory_resource (bytes is unable to satisfy the memory request from its own internal data structures,
it will call upstream_resource()->allocate() to obtain more memory.
If bytes is larger than that which the largest pool can handle,
then memory will be allocated using upstream_resource()->allocate().
upstream_resource()->allocate() throws.virtual void do_deallocate(void* p, size_t bytes, size_t alignment);
p to the pool.
It is unspecified if or under what circumstances this operation will result in a call to upstream_resource()->deallocate().virtual bool unsynchronized_pool_resource::do_is_equal( const memory_resource& other) const noexcept;
this == dynamic_cast(&other) .virtual bool synchronized_pool_resource::do_is_equal( const memory_resource& other) const noexcept;
this == dynamic_cast(&other) .monotonic_buffer_resourcemonotonic_buffer_resource overview
A monotonic_buffer_resource is a special-purpose memory resource
intended for very fast memory allocations in situations where memory is used to build up a few objects
and then is released all at once when the memory resource object is destroyed.
It has the following qualities:
deallocate has no effect,
thus the amount of memory consumed increases monotonically until the resource is destroyed.allocate and deallocate do not synchronize with one another.deallocate has not been called for some of the allocated blocks.class monotonic_buffer_resource : public memory_resource {
memory_resource* upstream_rsrc; // exposition only
void* current_buffer; // exposition only
size_t next_buffer_size; // exposition only
public:
explicit monotonic_buffer_resource(memory_resource* upstream);
monotonic_buffer_resource(size_t initial_size,
memory_resource* upstream);
monotonic_buffer_resource(void* buffer, size_t buffer_size,
memory_resource* upstream);
monotonic_buffer_resource()
: monotonic_buffer_resource(get_default_resource()) { }
explicit monotonic_buffer_resource(size_t initial_size)
: monotonic_buffer_resource(initial_size,
get_default_resource()) { }
monotonic_buffer_resource(void* buffer, size_t buffer_size)
: monotonic_buffer_resource(buffer, buffer_size,
get_default_resource()) { }
monotonic_buffer_resource(const monotonic_buffer_resource&) = delete;
virtual ~monotonic_buffer_resource();
monotonic_buffer_resource operator=(
const monotonic_buffer_resource&) = delete;
void release();
memory_resource* upstream_resource() const;
protected:
virtual void* do_allocate(size_t bytes, size_t alignment);
virtual void do_deallocate(void* p, size_t bytes,
size_t alignment);
virtual bool do_is_equal(const memory_resource& other) const noexcept;
};
monotonic_buffer_resource constructor and destructorexplicit monotonic_buffer_resource(memory_resource* upstream); monotonic_buffer_resource(size_t initial_size, memory_resource* upstream);
upstream shall be the address of a valid memory resource.
initial_size, if specified, shall be greater than zero.upstream_rsrc to upstream and current_buffer to nullptr.
If initial_size is specified, sets next_buffer_size to at least initial_size;
otherwise sets next_buffer_size to an implementation-defined size.monotonic_buffer_resource(void* buffer, size_t buffer_size, memory_resource* upstream);
upstream shall be the address of a valid memory resource.
buffer_size shall be no larger than the number of bytes in buffer.upstream_rsrc to upstream, current_buffer to buffer, and next_buffer_size to initial_size (but not less than 1),
then increases next_buffer_size by an implementation-defined growth factor (which need not be integral).~monotonic_buffer_resource();
this->release().void release();
upstream_rsrc->deallocate() as necessary to release all allocated memory.upstream_rsrc even if some blocks that were allocated from this have not been deallocated from this.
— end note ]
memory_resource* upstream_resource() const;
upstream_rsrc.void* do_allocate(size_t bytes, size_t alignment);
bytes.
The size and alignment of the allocated memory shall meet the requirements for a class derived from memory_resource (current_buffer can fit a block with the specified bytes and alignment,
then allocate the return block from current_buffer;
otherwise set current_buffer to upstream_rsrc->allocate(n, m),
where n is not less than max(bytes, next_buffer_size) and m is not less than alignment,
and increase next_buffer_size by an implementation-defined growth factor (which need not be integral),
then allocate the return block from the newly-allocated current_buffer.
upstream_rsrc->allocate() throws.void do_deallocate(void* p, size_t bytes, size_t alignment);
bool do_is_equal(const memory_resource& other) const noexcept;
this == dynamic_cast(&other) .#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
namespace pmr {
// basic_string using polymorphic allocator in namespace pmr
template >
using basic_string =
std::basic_string>;
// basic_string typedef names using polymorphic allocator in namespace
// std::experimental::pmr
typedef basic_string string;
typedef basic_string u16string;
typedef basic_string u32string;
typedef basic_string wstring;
} // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
namespace pmr {
template
using deque = std::deque>;
} // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
namespace pmr {
template
using forward_list =
std::forward_list>;
} // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
namespace pmr {
template
using list = std::list>;
} // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
namespace pmr {
template
using vector = std::vector>;
} // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
#include
#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
namespace pmr {
template >
using set = std::set>;
template >
using multiset = std::multiset>;
} // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
namespace pmr {
template ,
class Pred = equal_to>
using unordered_map =
std::unordered_map>>;
template ,
class Pred = equal_to>
using unordered_multimap =
std::unordered_multimap>>;
} // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
namespace pmr {
template ,
class Pred = equal_to>
using unordered_set = std::unordered_set>;
template ,
class Pred = equal_to>
using unordered_multiset =
std::unordered_multiset>;
} // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
#include
#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
namespace pmr {
template
using match_results =
std::match_results>>;
typedef match_results cmatch;
typedef match_results wcmatch;
typedef match_results smatch;
typedef match_results wsmatch;
} // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
A non-owning pointer, known as an observer, is an object o that stores a pointer to a second object, w.
In this context, w is known as a watched object.
nullptr.
— end note ]
o and w.
Specializations of observer_ptr shall meet the requirements of a CopyConstructible and CopyAssignable type.
The template parameter W of an observer_ptr shall not be a reference type, but may be an incomplete type.
observer_ptr include clarity of interface specification in new code,
and interoperability with pointer-based legacy code.
— end note ]
observer_ptr overviewnamespace std {
namespace experimental {
inline namespace fundamentals_v2 {
template class observer_ptr {
public:
// publish our template parameter and variations thereof
using element_type = W;
using pointer = add_pointer_t; // exposition-only
using reference = add_lvalue_reference_t; // exposition-only
// 8.12.2, observer_ptr constructors
// default c’tor
constexpr observer_ptr() noexcept;
// pointer-accepting c’tors
constexpr observer_ptr(nullptr_t) noexcept;
constexpr explicit observer_ptr(pointer) noexcept;
// copying c’tors (in addition to compiler-generated copy c’tor)
template constexpr observer_ptr(observer_ptr) noexcept;
// 8.12.3, observer_ptr observers
constexpr pointer get() const noexcept;
constexpr reference operator*() const;
constexpr pointer operator->() const noexcept;
constexpr explicit operator bool() const noexcept;
// 8.12.4, observer_ptr conversions
constexpr explicit operator pointer() const noexcept;
// 8.12.5, observer_ptr modifiers
constexpr pointer release() noexcept;
constexpr void reset(pointer = nullptr) noexcept;
constexpr void swap(observer_ptr&) noexcept;
}; // observer_ptr<>
} // inline namespace fundamentals_v2
} // namespace experimental
} // namespace std
observer_ptr constructorsconstexpr observer_ptr() noexcept; constexpr observer_ptr(nullptr_t) noexcept;
get() == nullptr.constexpr explicit observer_ptr(pointer other) noexcept;
get() == other.template constexpr observer_ptr(observer_ptr other) noexcept;
get() == other.get().W2* is convertible to W*.observer_ptr observersconstexpr pointer get() const noexcept;
constexpr reference operator*() const;
get() != nullptr.*get().constexpr pointer operator->() const noexcept;
get().constexpr explicit operator bool() const noexcept;
get() != nullptr.observer_ptr conversionsconstexpr explicit operator pointer() const noexcept;
get().observer_ptr modifiersconstexpr pointer release() noexcept;
get() == nullptr.get() had at the start of the call to release.constexpr void reset(pointer p = nullptr) noexcept;
get() == p.constexpr void swap(observer_ptr& other) noexcept;
swap on the stored pointers of *this and other.observer_ptr specialized algorithmstemplate
void swap(observer_ptr& p1, observer_ptr& p2) noexcept;
p1.swap(p2).template observer_ptr make_observer(W* p) noexcept;
observer_ptr{p} .template
bool operator==(observer_ptr p1, observer_ptr p2);
p1.get() == p2.get().template
bool operator!=(observer_ptr p1, observer_ptr p2);
not (p1 == p2).template
bool operator==(observer_ptr p, nullptr_t) noexcept; template
bool operator==(nullptr_t, observer_ptr p) noexcept;
not p.template
bool operator!=(observer_ptr p, nullptr_t) noexcept; template
bool operator!=(nullptr_t, observer_ptr p) noexcept;
(bool)p.template
bool operator<(observer_ptr p1, observer_ptr p2);
less()(p1.get(), p2.get()) ,
where W3 is the composite pointer type (W1* and W2*.
template
bool operator>(observer_ptr p1, observer_ptr p2);
p2 < p1.template
bool operator<=(observer_ptr p1, observer_ptr p2);
not (p2 < p1).template
bool operator>=(observer_ptr p1, observer_ptr p2);
not (p1 < p2).observer_ptr hash supporttemplate struct hash>;
The template specialization shall meet the requirements of class template hash (p of type observer_ptr,
hash shall evaluate to the same value as hash.
For brevity, this section specifies the contents of 9 headers,
each of which behaves as described by
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
// 9.1.2, Function template erase_if
// 9.1.3, Function template erase
//
template
void erase_if(basic_string& c, Predicate pred);
template
void erase(basic_string& c, const U& value);
//
template
void erase_if(deque& c, Predicate pred);
template
void erase(deque& c, const U& value);
//
template
void erase_if(vector& c, Predicate pred);
template
void erase(vector& c, const U& value);
//
template
void erase_if(forward_list& c, Predicate pred);
template
void erase(forward_list& c, const U& value);
//
template
void erase_if(list& c, Predicate pred);
template
void erase(list& c, const U& value);
//
template
void erase_if(map& c, Predicate pred);
template
void erase_if(multimap& c, Predicate pred);
//
template
void erase_if(set& c, Predicate pred);
template
void erase_if(multiset& c, Predicate pred);
//
template
void erase_if(unordered_map& c, Predicate pred);
template
void erase_if(unordered_multimap& c, Predicate pred);
//
template
void erase_if(unordered_set& c, Predicate pred);
template
void erase_if(unordered_multiset& c, Predicate pred);
} // inline namespace fundamentals_v2
} // namespace experimental
} // namespace std
erase_iftemplate
void erase_if(basic_string& c, Predicate pred); template
void erase_if(deque& c, Predicate pred); template
void erase_if(vector& c, Predicate pred);
c.erase(remove_if(c.begin(), c.end(), pred), c.end());template
void erase_if(forward_list& c, Predicate pred); template
void erase_if(list& c, Predicate pred);
c.remove_if(pred);template
void erase_if(map& c, Predicate pred); template
void erase_if(multimap& c, Predicate pred); template
void erase_if(set& c, Predicate pred); template
void erase_if(multiset& c, Predicate pred); template
void erase_if(unordered_map& c, Predicate pred); template
void erase_if(unordered_multimap& c, Predicate pred); template
void erase_if(unordered_set& c, Predicate pred); template
void erase_if(unordered_multiset& c, Predicate pred);
for (auto i = c.begin(), last = c.end(); i != last; ) {
if (pred(*i)) {
i = c.erase(i);
} else {
++i;
}
}template
void erase(basic_string& c, const U& value); template
void erase(deque& c, const U& value); template
void erase(vector& c, const U& value);
c.erase(remove(c.begin(), c.end(), value), c.end());template
void erase(forward_list& c, const U& value); template
void erase(list& c, const U& value);
erase_if(c, [&](auto& elem) { return elem == value; });erase() for associative containers and unordered associative containers are intentionally not provided.
— end note ]
array#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
// 9.2.2, Array creation functions
template
constexpr array<VT, sizeof...(Types)> make_array(Types&&... t);
template
constexpr array, N> to_array(T (&a)[N]);
} // inline namespace fundamentals_v2
} // namespace experimental
} // namespace std
template
constexpr array<VT, sizeof...(Types)> make_array(Types&&... t);
Let Ui be decay_t<Ti> for each Ti in Types.
D is void and at least one Ui is a specialization of reference_wrapper.
array<VT, sizeof...(Types)>{ std::forward(t)... } , where VT is common_type_t if D is void, otherwise VT is D.
int i = 1; int& ri = i;
auto a1 = make_array(i, ri); // a1 is of type array
auto a2 = make_array(i, ri, 42L); // a2 is of type array
auto a3 = make_array(i, ri); // a3 is of type array
auto a4 = make_array(); // a4 is of type array
auto a5 = make_array(); // ill-formed
— end example ]
template
constexpr array, N> to_array(T (&a)[N]);
array, N> such that each element is copy-initialized with the corresponding element of a.
synopsis#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
// 10.2, Class template ostream_joiner
template >
class ostream_joiner;
template
ostream_joiner, charT, traits>
make_ostream_joiner(basic_ostream& os, DelimT&& delimiter);
} // inline namespace fundamentals_v2
} // namespace experimental
} // namespace std
ostream_joiner
ostream_joiner writes (using operator<<) successive elements onto the output stream from which it was constructed.
The delimiter that it was constructed with is written to the stream between every two Ts that are written.
It is not possible to get a value out of the output iterator.
Its only use is as an output iterator in situations like
while (first != last)
*result++ = *first++;
ostream_joiner is defined as
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
template >
class ostream_joiner {
public:
typedef charT char_type;
typedef traits traits_type;
typedef basic_ostream ostream_type;
typedef output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
ostream_joiner(ostream_type& s, const DelimT& delimiter);
ostream_joiner(ostream_type& s, DelimT&& delimiter);
template
ostream_joiner& operator=(const T& value);
ostream_joiner& operator*() noexcept;
ostream_joiner& operator++() noexcept;
ostream_joiner& operator++(int) noexcept;
private:
ostream_type* out_stream; // exposition only
DelimT delim; // exposition only
bool first_element; // exposition only
};
} // inline namespace fundamentals_v2
} // namespace experimental
} // namespace std
ostream_joiner constructorostream_joiner(ostream_type& s, const DelimT& delimiter);
out_stream with std::addressof(s),
delim with delimiter,
and first_element with true.
ostream_joiner(ostream_type& s, DelimT&& delimiter);
out_stream with std::addressof(s),
delim with move(delimiter),
and first_element with true.
ostream_joiner operationstemplate
ostream_joiner& operator=(const T& value);
if (!first_element)
*out_stream << delim;
first_element = false;
*out_stream << value;
return *this;
ostream_joiner& operator*() noexcept;
*this.ostream_joiner& operator++() noexcept; ostream_joiner& operator++(int) noexcept;
*this.ostream_joiner creation functiontemplate
ostream_joiner, charT, traits>
make_ostream_joiner(basic_ostream& os, DelimT&& delimiter);
ostream_joiner, charT, traits>(os, forward(delimiter)); #include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
template class promise;
template class promise;
template <> class promise;
template
void swap(promise& x, promise& y) noexcept;
template class packaged_task; // undefined
template
class packaged_task;
template
void swap(packaged_task&, packaged_task&) noexcept;
} // namespace fundamentals_v2
} // namespace experimental
template
struct uses_allocator, Alloc>;
template
struct uses_allocator, Alloc>;
} // namespace std
promise
The specification of all declarations within this sub-clause
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
template
class promise {
public:
typedef erased_type allocator_type;
promise();
template
promise(allocator_arg_t, const Allocator& a);
promise(promise&& rhs) noexcept;
promise(const promise& rhs) = delete;
~promise();
promise& operator=(promise&& rhs) noexcept;
promise& operator=(const promise& rhs) = delete;
void swap(promise& other) noexcept;
future get_future();
void set_value(see below);
void set_exception(exception_ptr p);
void set_value_at_thread_exit(const R& r);
void set_value_at_thread_exit(see below);
void set_exception_at_thread_exit(exception_ptr p);
pmr::memory_resource* get_memory_resource();
};
template
void swap(promise& x, promise& y) noexcept;
} // namespace fundamentals_v2
} // namespace experimental
template
struct uses_allocator, Alloc>;
} // namespace std
When a promise constructor that takes a first argument of type allocator_arg_t is invoked,
the second argument is treated as a type-erased allocator (
packaged_task
The specification of all declarations within this sub-clause
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
template
class packaged_task {
public:
typedef erased_type allocator_type;
packaged_task() noexcept;
template
explicit packaged_task(F&& f);
template
explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f);
~packaged_task();
packaged_task(const packaged_task&) = delete;
packaged_task& operator=(const packaged_task&) = delete;
packaged_task(packaged_task&& rhs) noexcept;
packaged_task& operator=(packaged_task&& rhs) noexcept;
void swap(packaged_task& other) noexcept;
bool valid() const noexcept;
future get_future();
void operator()(ArgTypes... );
void make_ready_at_thread_exit(ArgTypes...);
void reset();
pmr::memory_resource* get_memory_resource();
};
template
void swap(packaged_task&, packaged_task&) noexcept;
} // namespace fundamentals_v2
} // namespace experimental
template
struct uses_allocator, Alloc>;
} // namespace std
When a packaged_task constructor that takes a first argument of type allocator_arg_t is invoked,
the second argument is treated as a type-erased allocator (
synopsis#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
// 12.2, Search
template
ForwardIterator search(ForwardIterator first, ForwardIterator last,
const Searcher& searcher);
// 12.3, Sampling
template
SampleIterator sample(PopulationIterator first, PopulationIterator last,
SampleIterator out, Distance n);
template
SampleIterator sample(PopulationIterator first, PopulationIterator last,
SampleIterator out, Distance n,
UniformRandomNumberGenerator&& g);
// 12.4, Shuffle
template
void shuffle(RandomAccessIterator first, RandomAccessIterator last);
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
template
ForwardIterator search(ForwardIterator first, ForwardIterator last,
const Searcher& searcher);
return searcher(first, last);Searcher need not meet the CopyConstructible requirements.template
SampleIterator sample(PopulationIterator first, PopulationIterator last,
SampleIterator out, Distance n);
template
SampleIterator sample(PopulationIterator first, PopulationIterator last,
SampleIterator out, Distance n,
UniformRandomNumberGenerator&& g);
PopulationIterator shall meet the requirements of an InputIterator type.SampleIterator shall meet the requirements of an OutputIterator type.SampleIterator shall meet the additional requirements of a RandomAccessIterator type
unless PopulationIterator meets the additional requirements of a ForwardIterator type.PopulationIterator's value type shall be writable to out.Distance shall be an integer type.UniformRandomNumberGenerator shall meet the requirements of a uniform random number generator type (Distance.out shall not be in the range first, last)min(last−first, n) elements (the sample)
from first, last)out
such that each possible sample has equal probability of appearance.
last - first).PopulationIterator meets the
requirements of a ForwardIterator type.g is not given in the argument list, it denotes
the per-thread engine (g shall serve as the
implementation’s source of randomness.template
void shuffle(RandomAccessIterator first, RandomAccessIterator last);
[first,last)
such that each possible permutation of those elements has equal
probability of appearance.RandomAccessIterator shall satisfy the
requirements of ValueSwappable ((last - first) - 1 swaps.#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
// 13.1.2, Greatest common divisor
template
constexpr common_type_t gcd(M m, N n);
// 13.1.3, Least common multiple
template
constexpr common_type_t lcm(M m, N n);
} // inline namespace fundamentals_v2
} // namespace experimental
} // namespace std
template
constexpr common_type_t gcd(M m, N n);
|m| shall be representable as a value of type M and
|n| shall be representable as a value of type N.
gcd(m, m) = |m| is representable as a value of type M.
— end note ]
M or N is not an integer type, the program is ill-formed.m and n are both zero.
Otherwise, returns the greatest common divisor of |m| and |n|.template
constexpr common_type_t lcm(M m, N n);
|m| shall be representable as a value of type M and
|n| shall be representable as a value of type N.
The least common multiple of |m| and |n|
shall be representable as a value of type common_type_t.
M or N is not an integer type, the program is ill-formed.m or n is zero.
Otherwise, returns the least common multiple of |m| and |n|.
synopsis#include
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
// 13.2.2.1, Function template randint
template
IntType randint(IntType a, IntType b);
void reseed();
void reseed(default_random_engine::result_type value);
} // inline namespace fundamentals_v2
} // namespace experimental
} // namespace std
randintA separate per-thread engine of type default_random_engine
(
template
IntType randint(IntType a, IntType b);
a ≤ b.IntType (a ≤ i ≤ b,
produced from a thread-local instance of uniform_int_distribution
(void reseed(); void reseed(default_random_engine::result_type value);
g be the per-thread engine. The first
form sets g to an unpredictable state. The second form
invokes g.seed(value).randint do not
depend on values produced by g before calling reseed.
reseed also resets any instances of uniform_int_distribution
used by randint.
— end note ]
source_location synopsisnamespace std {
namespace experimental {
inline namespace fundamentals_v2 {
struct source_location {
// 14.1.2, source_location creation
static constexpr source_location current() noexcept;
constexpr source_location() noexcept;
// 14.1.3, source_location field access
constexpr uint_least32_t line() const noexcept;
constexpr uint_least32_t column() const noexcept;
constexpr const char* file_name() const noexcept;
constexpr const char* function_name() const noexcept;
};
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
source_location is to have a small size and efficient copying.
— end note ]
source_location creationstatic constexpr source_location current() noexcept;
current,
returns a source_location with an implementation-defined value.
The value should be affected by #line
(__LINE__ and __FILE__.
If invoked in some other way, the value returned is unspecified.
current should correspond to the location of
the constructor or aggregate initialization that initializes the member.
source_location will be the location of the call to current at the call site.
— end note ]
struct s {
source_location member = source_location::current();
int other_member;
s(source_location loc = source_location::current())
: member(loc) // values of member will be from call-site
{}
s(int blather) : // values of member should be hereabouts
other_member(blather) {}
s(double) // values of member should be hereabouts
{}
};
void f(source_location a = source_location::current()) {
source_location b = source_location::current(); // values in b represent this line
}
void g() {
f(); // f’s first argument corresponds to this line of code
source_location c = source_location::current();
f(c); // f’s first argument gets the same values as c, above
}
— end example ]
constexpr source_location() noexcept;
source_location.source_location field accessconstexpr uint_least32_t line() const noexcept;
constexpr uint_least32_t column() const noexcept;
constexpr const char* file_name() const noexcept;
constexpr const char* function_name() const noexcept;