C++ Extensions for Library Fundamentals, Version 2, Working Draft (original) (raw)

Note: this is an early draft. It’s known to be incomplet and incorrekt, and it has lots of bad formatting.

Contents

  1. 1General
    1. 1.1Scope
    2. 1.2Normative references
    3. 1.3Namespaces, headers, and modifications to standard classes
    4. 1.4Terms and definitions
    5. 1.5Future plans (Informative)
    6. 1.6Feature-testing recommendations (Informative)
  2. 2Modifications to the C++ Standard Library
    1. 2.1Uses-allocator construction
  3. 3General utilities library
    1. 3.1Utility components
      1. 3.1.1Header <experimental/utility> synopsis
      2. 3.1.2Class erased_type
    2. 3.2Tuples
      1. 3.2.1Header <experimental/tuple> synopsis
      2. 3.2.2Calling a function with a tuple of arguments
    3. 3.3Metaprogramming and type traits
      1. 3.3.1Header <experimental/type_traits> synopsis
      2. 3.3.2Other type transformations
      3. 3.3.3Logical operator traits
      4. 3.3.4Detection idiom
    4. 3.4Compile-time rational arithmetic
      1. 3.4.1Header <experimental/ratio> synopsis
    5. 3.5Time utilities
      1. 3.5.1Header <experimental/chrono> synopsis
    6. 3.6System error support
      1. 3.6.1Header <experimental/system_error> synopsis
    7. 3.7Class template propagate_const
      1. 3.7.1Class template propagate_const general
      2. 3.7.2Header <experimental/propagate_const> synopsis
      3. 3.7.3propagate_const requirements on T
        1. 3.7.3.1propagate_const requirements on class type T
      4. 3.7.4propagate_const constructors
      5. 3.7.5propagate_const assignment
      6. 3.7.6propagate_const const observers
      7. 3.7.7propagate_const non-const observers
      8. 3.7.8propagate_const modifiers
      9. 3.7.9propagate_const relational operators
      10. 3.7.10propagate_const specialized algorithms
      11. 3.7.11propagate_const underlying pointer access
      12. 3.7.12propagate_const hash support
      13. 3.7.13propagate_const comparison function objects
  4. 4Function objects
    1. 4.1Header <experimental/functional> synopsis
    2. 4.2Class template function
      1. 4.2.1function construct/copy/destroy
      2. 4.2.2function modifiers
    3. 4.3Searchers
      1. 4.3.1Class template default_searcher
        1. 4.3.1.1default_searcher creation functions
      2. 4.3.2Class template boyer_moore_searcher
        1. 4.3.2.1boyer_moore_searcher creation functions
      3. 4.3.3Class template boyer_moore_horspool_searcher
        1. 4.3.3.1boyer_moore_horspool_searcher creation functions
    4. 4.4Function template not_fn
  5. 5Optional objects
    1. 5.1In general
    2. 5.2Header <experimental/optional> synopsis
    3. 5.3optional for object types
      1. 5.3.1Constructors
      2. 5.3.2Destructor
      3. 5.3.3Assignment
      4. 5.3.4Swap
      5. 5.3.5Observers
    4. 5.4In-place construction
    5. 5.5No-value state indicator
    6. 5.6Class bad_optional_access
    7. 5.7Relational operators
    8. 5.8Comparison with nullopt
    9. 5.9Comparison with T
    10. 5.10Specialized algorithms
    11. 5.11Hash support
  6. 6Class any
    1. 6.1Header <experimental/any> synopsis
    2. 6.2Class bad_any_cast
    3. 6.3Class any
      1. 6.3.1any construct/destruct
      2. 6.3.2any assignments
      3. 6.3.3any modifiers
      4. 6.3.4any observers
    4. 6.4Non-member functions
  7. 7string_view
    1. 7.1Header <experimental/string_view> synopsis
    2. 7.2Class template basic_string_view
    3. 7.3basic_string_view constructors and assignment operators
    4. 7.4basic_string_view iterator support
    5. 7.5basic_string_view capacity
    6. 7.6basic_string_view element access
    7. 7.7basic_string_view modifiers
    8. 7.8basic_string_view string operations
      1. 7.8.1Searching basic_string_view
    9. 7.9basic_string_view non-member comparison functions
    10. 7.10Inserters and extractors
    11. 7.11Hash support
  8. 8Memory
    1. 8.1Header <experimental/memory> synopsis
    2. 8.2Shared-ownership pointers
      1. 8.2.1Class template shared_ptr
        1. 8.2.1.1shared_ptr constructors
        2. 8.2.1.2shared_ptr observers
        3. 8.2.1.3shared_ptr casts
        4. 8.2.1.4shared_ptr hash support
      2. 8.2.2Class template weak_ptr
        1. 8.2.2.1weak_ptr constructors
    3. 8.3Type-erased allocator
    4. 8.4Header <experimental/memory_resource> synopsis
    5. 8.5Class memory_resource
      1. 8.5.1Class memory_resource overview
      2. 8.5.2memory_resource public member functions
      3. 8.5.3memory_resource protected virtual member functions
      4. 8.5.4memory_resource equality
    6. 8.6Class template polymorphic_allocator
      1. 8.6.1Class template polymorphic_allocator overview
      2. 8.6.2polymorphic_allocator constructors
      3. 8.6.3polymorphic_allocator member functions
      4. 8.6.4polymorphic_allocator equality
    7. 8.7template alias resource_adaptor
      1. 8.7.1resource_adaptor
      2. 8.7.2resource_adaptor_imp constructors
      3. 8.7.3resource_adaptor_imp member functions
    8. 8.8Access to program-wide memory_resource objects
    9. 8.9Pool resource classes
      1. 8.9.1Classes synchronized_pool_resource and unsynchronized_pool_resource
      2. 8.9.2pool_options data members
      3. 8.9.3pool resource constructors and destructors
      4. 8.9.4pool resource members
    10. 8.10Class monotonic_buffer_resource
      1. 8.10.1Class monotonic_buffer_resource overview
      2. 8.10.2monotonic_buffer_resource constructor and destructor
      3. 8.10.3monotonic_buffer_resource members
    11. 8.11Alias templates using polymorphic memory resources
      1. 8.11.1Header <experimental/string> synopsis
      2. 8.11.2Header <experimental/deque> synopsis
      3. 8.11.3Header <experimental/forward_list> synopsis
      4. 8.11.4Header <experimental/list> synopsis
      5. 8.11.5Header <experimental/vector> synopsis
      6. 8.11.6Header <experimental/map> synopsis
      7. 8.11.7Header <experimental/set> synopsis
      8. 8.11.8Header <experimental/unordered_map> synopsis
      9. 8.11.9Header <experimental/unordered_set> synopsis
      10. 8.11.10Header <experimental/regex> synopsis
    12. 8.12Non-owning pointers
      1. 8.12.1Class template observer_ptr overview
      2. 8.12.2observer_ptr constructors
      3. 8.12.3observer_ptr observers
      4. 8.12.4observer_ptr conversions
      5. 8.12.5observer_ptr modifiers
      6. 8.12.6observer_ptr specialized algorithms
      7. 8.12.7observer_ptr hash support
  9. 9Containers
    1. 9.1Uniform container erasure
      1. 9.1.1Header synopsis
      2. 9.1.2Function template erase_if
      3. 9.1.3Function template erase
    2. 9.2Class template array
      1. 9.2.1Header <experimental/array> synopsis
      2. 9.2.2Array creation functions
  10. 10Iterators library
  11. 10.1Header <experimental/iterator> synopsis
  12. 10.2Class template ostream_joiner
    1. 10.2.1ostream_joiner constructor
    2. 10.2.2ostream_joiner operations
    3. 10.2.3ostream_joiner creation function
  13. 11Futures
  14. 11.1Header <experimental/future> synopsis
  15. 11.2Class template promise
  16. 11.3Class template packaged_task
  17. 12Algorithms library
  18. 12.1Header <experimental/algorithm> synopsis
  19. 12.2Search
  20. 12.3Sampling
  21. 12.4Shuffle
  22. 13Numerics library
  23. 13.1Generalized numeric operations
    1. 13.1.1Header <experimental/numeric> synopsis
    2. 13.1.2Greatest common divisor
    3. 13.1.3Least common multiple
  24. 13.2Random number generation
    1. 13.2.1Header <experimental/random> synopsis
    2. 13.2.2Utilities
      1. 13.2.2.1Function template randint
  25. 14Reflection library
  26. 14.1Class source_location
    1. 14.1.1Header <experimental/source_location> synopsis
    2. 14.1.2source_location creation
    3. 14.1.3source_location field access

1

General

[general]

1.1

Scope

[general.scope]

This technical specification describes extensions to the C++ Standard Library (1.2). These extensions are classes and functions that are likely to be used widely within a program and/or on the interface boundaries between libraries written by different organizations.

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.

1.2

Normative references

[general.references]

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 (C++14 §17) is included into this Technical Specification by reference.

1.3

Namespaces, headers, and modifications to standard classes

[general.namespaces]

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 namespacestd. Unless otherwise specified, all components described in this technical specification either:

Each header described in this technical specification shall import the contents ofstd::experimental::fundamentals_v2 intostd::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 <meow> are provided inside the<experimental/meow> header, which shall include the standard contents of <meow> as if by

#include <meow>

New headers are also provided in the<experimental/> directory, but without such an#include.

1.4

Terms and definitions

[general.defns]

For the purposes of this document, the terms and definitions given in the C++ Standard and the following apply.

1.4.1[general.defns.direct-non-list-init]
direct-non-list-initialization

A direct-initialization that is not list-initialization.

1.5

Future plans (Informative)

[general.plans]

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 instd::experimental::fundamentals_v3,std::experimental::fundamentals_v4, etc., with the most recent implemented version inlined intostd::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 theexperimental/ prefix from its header's path.

1.6

Feature-testing recommendations (Informative)

[general.feature.test]

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.[ _Note:_ WG21's SD-6 makes similar recommendations for the C++ Standard itself.— end note ]

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(<header/name>)) 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.)

Table 2 — Significant features in this technical specification

Doc. No. Title Primary Section Macro Name Suffix Value Header
N3915 apply() call a function with arguments from a tuple 3.2.2 apply 201402 <experimental/tuple>
N3932 Variable Templates For Type Traits 3.3.1 type_trait_variable_templates 201402 <experimental/type_traits>
N3866 Invocation type traits 3.3.2 invocation_type 201406 <experimental/type_traits>
P0013R1 Logical Operator Type Traits 3.3.3 logical_traits 201511 <experimental/type_traits>
N4502 The C++ Detection Idiom 3.3.4 detect 201505 <experimental/type_traits>
N4388 A Proposal to Add a Const-Propagating Wrapper to the Standard Library 3.7 propagate_const 201505 <experimental/propagate_const>
N3916 Type-erased allocator for std::function 4.2 function_erased_allocator 201406 <experimental/functional>
N3905 Extending std::search to use Additional Searching Algorithms 4.3 boyer_moore_searching 201411 <experimental/functional>
N4076 A proposal to add a generalized callable negator 4.4 not_fn 201406 <experimental/functional>
N3672, N3793 A utility class to represent optional objects 5 optional 201411 <experimental/optional>
N3804 Any Library Proposal 6 any 201411 <experimental/any>
N3921 string_view: a non-owning reference to a string 7 string_view 201411 <experimental/string_view>
N3920 Extending shared_ptr to Support Arrays 8.2 shared_ptr_arrays 201406 <experimental/memory>
N3916 Polymorphic Memory Resources 8.4 memory_resources 201402 <experimental/memory_resource>
N4282 The World’s Dumbest Smart Pointer 8.12 observer_ptr 201411 <experimental/memory>
N4273 Uniform Container Erasure 9.1 erase_if 201411 <experimental/vector>
N4391 make_array 9.2.2 make_array 201505 <experimental/array>
N4257 Delimited iterators 10.2 ostream_joiner 201411 <experimental/iterator>
N3916 Type-erased allocator for std::promise 11.2 promise_erased_allocator 201406 <experimental/future>
N3916 Type-erased allocator for std::packaged_task 11.3 packaged_task_erased_allocator 201406 <experimental/future>
N3925 A sample Proposal 12.3 sample 201402 <experimental/algorithm>
N4061 Greatest Common Divisor and Least Common Multiple 13.1.2, 13.1.3 gcd_lcm 201411 <experimental/numeric>
N4531 std::rand replacement 13.2.2.1 randint 201511 <experimental/random>
N4519 Source-Code Information Capture 14.1 source_location 201505 <experimental/source_location>

2

Modifications to the C++ Standard Library

[mods]

Implementations that conform to this technical specification shall behave as if the modifications contained in this section are made to the C++ Standard.

2.1

Uses-allocator construction

[mods.allocator.uses]

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.[ Note: Existing programs that use standard allocators would be unaffected by this change.— end note ]

20.7.7 uses_allocator [allocator.uses]

20.7.7.1 uses_allocator trait [allocator.uses.trait]

template <class T, class Alloc> struct uses_allocator;

Remarks:

Automatically detects whether T has a nested allocator_type that is convertible from Alloc. Meets the BinaryTypeTrait requirements (C++14 §20.10.1). The implementation shall provide a definition that is derived from true_type if a type T::allocator_type exists and either is_convertible_v<Alloc, T::allocator_type> != false or T::allocator_type is an alias for std::experimental::erased_type (3.1.2), otherwise it shall be derived from false_type. A program may specialize this template to derive from true_type for a user-defined type T that does not have a nested allocator_type but nonetheless can be constructed with an allocator where either:

20.7.7.2 uses-allocator construction [allocator.uses.construction]

Uses-allocator construction with allocator Alloc refers to the construction of an object obj of type T, using constructor arguments v1, v2, ..., vN of types V1, V2, ..., VN, respectively, and an allocator alloc of type Alloc,where Alloc either (1) meets the requirements of an allocator (C++14 §17.6.3.5), or (2) is a pointer type convertible to std::experimental::pmr::memory_resource* (8.5), according to the following rules:

3

General utilities library

[utilities]

3.1

Utility components

[utility]

3.1.1

Header <experimental/utility> synopsis

[utility.synop]

#include <utility>

namespace std {
namespace experimental {
inline namespace fundamentals_v2 {

  // 3.1.2, Class erased_type
  struct erased_type { };

} // namespace fundamentals_v2
} // namespace experimental
} // namespace std

3.1.2

Class erased_type

[utility.erased.type]

struct 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 8.3).

3.2

Tuples

[tuple]

3.2.2

Calling a function with a tuple of arguments

[tuple.apply]

template <class F, class Tuple>
constexpr decltype(auto) apply(F&& f, Tuple&& t);

Effects:

Given the exposition only function

template <class F, class Tuple, size_t... I>
constexpr decltype(auto) apply_impl(  // exposition only
    F&& f, Tuple&& t, index_sequence<I...>) {
  return INVOKE(std::forward<F>(f), std::get<I>(std::forward<Tuple>(t))...);
}

Equivalent to

return apply_impl(std::forward<F>(f), std::forward<Tuple>(t),
    make_index_sequence<tuple_size_v<decay_t<Tuple>>>{});

3.3

Metaprogramming and type traits

[meta]

3.3.1

Header <experimental/type_traits> synopsis

[meta.type.synop]

#include <type_traits>

namespace std {
namespace experimental {
inline namespace fundamentals_v2 {

  // See C++14 §20.10.4.1, primary type categories
  template <class T> constexpr bool is_void_v
    = is_void<T>::value;
  template <class T> constexpr bool is_null_pointer_v
    = is_null_pointer<T>::value;
  template <class T> constexpr bool is_integral_v
    = is_integral<T>::value;
  template <class T> constexpr bool is_floating_point_v
    = is_floating_point<T>::value;
  template <class T> constexpr bool is_array_v
    = is_array<T>::value;
  template <class T> constexpr bool is_pointer_v
    = is_pointer<T>::value;
  template <class T> constexpr bool is_lvalue_reference_v
    = is_lvalue_reference<T>::value;
  template <class T> constexpr bool is_rvalue_reference_v
    = is_rvalue_reference<T>::value;
  template <class T> constexpr bool is_member_object_pointer_v
    = is_member_object_pointer<T>::value;
  template <class T> constexpr bool is_member_function_pointer_v
    = is_member_function_pointer<T>::value;
  template <class T> constexpr bool is_enum_v
    = is_enum<T>::value;
  template <class T> constexpr bool is_union_v
    = is_union<T>::value;
  template <class T> constexpr bool is_class_v
    = is_class<T>::value;
  template <class T> constexpr bool is_function_v
    = is_function<T>::value;

  // See C++14 §20.10.4.2, composite type categories
  template <class T> constexpr bool is_reference_v
    = is_reference<T>::value;
  template <class T> constexpr bool is_arithmetic_v
    = is_arithmetic<T>::value;
  template <class T> constexpr bool is_fundamental_v
    = is_fundamental<T>::value;
  template <class T> constexpr bool is_object_v
    = is_object<T>::value;
  template <class T> constexpr bool is_scalar_v
    = is_scalar<T>::value;
  template <class T> constexpr bool is_compound_v
    = is_compound<T>::value;
  template <class T> constexpr bool is_member_pointer_v
    = is_member_pointer<T>::value;

  // See C++14 §20.10.4.3, type properties
  template <class T> constexpr bool is_const_v
    = is_const<T>::value;
  template <class T> constexpr bool is_volatile_v
    = is_volatile<T>::value;
  template <class T> constexpr bool is_trivial_v
    = is_trivial<T>::value;
  template <class T> constexpr bool is_trivially_copyable_v
    = is_trivially_copyable<T>::value;
  template <class T> constexpr bool is_standard_layout_v
    = is_standard_layout<T>::value;
  template <class T> constexpr bool is_pod_v
    = is_pod<T>::value;
  template <class T> constexpr bool is_literal_type_v
    = is_literal_type<T>::value;
  template <class T> constexpr bool is_empty_v
    = is_empty<T>::value;
  template <class T> constexpr bool is_polymorphic_v
    = is_polymorphic<T>::value;
  template <class T> constexpr bool is_abstract_v
    = is_abstract<T>::value;
  template <class T> constexpr bool is_final_v
    = is_final<T>::value;
  template <class T> constexpr bool is_signed_v
    = is_signed<T>::value;
  template <class T> constexpr bool is_unsigned_v
    = is_unsigned<T>::value;
  template <class T, class... Args> constexpr bool is_constructible_v
    = is_constructible<T, Args...>::value;
  template <class T> constexpr bool is_default_constructible_v
    = is_default_constructible<T>::value;
  template <class T> constexpr bool is_copy_constructible_v
    = is_copy_constructible<T>::value;
  template <class T> constexpr bool is_move_constructible_v
    = is_move_constructible<T>::value;
  template <class T, class U> constexpr bool is_assignable_v
    = is_assignable<T, U>::value;
  template <class T> constexpr bool is_copy_assignable_v
    = is_copy_assignable<T>::value;
  template <class T> constexpr bool is_move_assignable_v
    = is_move_assignable<T>::value;
  template <class T> constexpr bool is_destructible_v
    = is_destructible<T>::value;
  template <class T, class... Args> constexpr bool is_trivially_constructible_v
    = is_trivially_constructible<T, Args...>::value;
  template <class T> constexpr bool is_trivially_default_constructible_v
    = is_trivially_default_constructible<T>::value;
  template <class T> constexpr bool is_trivially_copy_constructible_v
    = is_trivially_copy_constructible<T>::value;
  template <class T> constexpr bool is_trivially_move_constructible_v
    = is_trivially_move_constructible<T>::value;
  template <class T, class U> constexpr bool is_trivially_assignable_v
    = is_trivially_assignable<T, U>::value;
  template <class T> constexpr bool is_trivially_copy_assignable_v
    = is_trivially_copy_assignable<T>::value;
  template <class T> constexpr bool is_trivially_move_assignable_v
    = is_trivially_move_assignable<T>::value;
  template <class T> constexpr bool is_trivially_destructible_v
    = is_trivially_destructible<T>::value;
  template <class T, class... Args> constexpr bool is_nothrow_constructible_v
    = is_nothrow_constructible<T, Args...>::value;
  template <class T> constexpr bool is_nothrow_default_constructible_v
    = is_nothrow_default_constructible<T>::value;
  template <class T> constexpr bool is_nothrow_copy_constructible_v
    = is_nothrow_copy_constructible<T>::value;
  template <class T> constexpr bool is_nothrow_move_constructible_v
    = is_nothrow_move_constructible<T>::value;
  template <class T, class U> constexpr bool is_nothrow_assignable_v
    = is_nothrow_assignable<T, U>::value;
  template <class T> constexpr bool is_nothrow_copy_assignable_v
    = is_nothrow_copy_assignable<T>::value;
  template <class T> constexpr bool is_nothrow_move_assignable_v
    = is_nothrow_move_assignable<T>::value;
  template <class T> constexpr bool is_nothrow_destructible_v
    = is_nothrow_destructible<T>::value;
  template <class T> constexpr bool has_virtual_destructor_v
    = has_virtual_destructor<T>::value;

  // See C++14 §20.10.5, type property queries
  template <class T> constexpr size_t alignment_of_v
    = alignment_of<T>::value;
  template <class T> constexpr size_t rank_v
    = rank<T>::value;
  template <class T, unsigned I = 0> constexpr size_t extent_v
    = extent<T, I>::value;

  // See C++14 §20.10.6, type relations
  template <class T, class U> constexpr bool is_same_v
    = is_same<T, U>::value;
  template <class Base, class Derived> constexpr bool is_base_of_v
    = is_base_of<Base, Derived>::value;
  template <class From, class To> constexpr bool is_convertible_v
    = is_convertible<From, To>::value;

  // 3.3.2, Other type transformations
  template <class> class invocation_type; // not defined
  template <class F, class... ArgTypes> class invocation_type<F(ArgTypes...)>;
  template <class> class raw_invocation_type; // not defined
  template <class F, class... ArgTypes> class raw_invocation_type<F(ArgTypes...)>;

  template <class T>
    using invocation_type_t = typename invocation_type<T>::type;
  template <class T>
    using raw_invocation_type_t = typename raw_invocation_type<T>::type;

  // 3.3.3, Logical operator traits
  template<class... B> struct conjunction;
  template<class... B> constexpr bool conjunction_v = conjunction<B...>::value;
  template<class... B> struct disjunction;
  template<class... B> constexpr bool disjunction_v = disjunction<B...>::value;
  template<class B> struct negation;
  template<class B> constexpr bool negation_v = negation<B>::value;

  // 3.3.4, Detection idiom
  template <class...> using void_t = void;

  struct nonesuch {
    nonesuch() = delete;
    ~nonesuch() = delete;
    nonesuch(nonesuch const&) = delete;

    void operator=(nonesuch const&) = delete;
  };

  template <template<class...> class Op, class... Args>
    using is_detected = see below;
  template <template<class...> class Op, class... Args>
    constexpr bool is_detected_v = is_detected<Op, Args...>::value;
  template <template<class...> class Op, class... Args>
    using detected_t = see below;
  template <class Default, template<class...> class Op, class... Args>
    using detected_or = see below;
  template <class Default, template<class...> class Op, class... Args>
    using detected_or_t = typename detected_or<Default, Op, Args...>::type;
  template <class Expected, template<class...> class Op, class... Args>
    using is_detected_exact = is_same<Expected, detected_t<Op, Args...>>;
  template <class Expected, template<class...> class Op, class... Args>
    constexpr bool is_detected_exact_v
      = is_detected_exact<Expected, Op, Args...>::value;
  template <class To, template<class...> class Op, class... Args>
    using is_detected_convertible = is_convertible<detected_t<Op, Args...>, To>;
  template <class To, template<class...> class Op, class... Args>
    constexpr bool is_detected_convertible_v
      = is_detected_convertible<To, Op, Args...>::value;

} // namespace fundamentals_v2
} // namespace experimental
} // namespace std

3.3.2

Other type transformations

[meta.trans.other]

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 TransformationTrait (C++14 §20.10.1).

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:

In all of the above cases, if an argument tI matches the ellipsis in the function's parameter-declaration-clause, the corresponding invocation parameter is defined to be the result of applying the default argument promotions (C++14 §5.2.2) to tI.

[ Example: Assume 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()(...);
};

Table 3 — Other type transformations

Template Condition Comments
template <class Fn, class... ArgTypes> struct raw_invocation_type<Fn(ArgTypes...)>; 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 <class Fn, class... ArgTypes> struct invocation_type<Fn(ArgTypes...)>; 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.[ Note: The compilation of the expression can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the "immediate context" and can result in the program being ill-formed.— end note ]

The nested typedef raw_invocation_type<Fn(ArgTypes...)>::type shall be defined as follows. If the expression _INVOKE_(declval<Fn>(), declval<ArgTypes>()...) is ill-formed when treated as an unevaluated operand (C++14 §5), there shall be no member type. Otherwise:

The nested typedef invocation_type<Fn(ArgTypes...)>::type shall be defined as follows. If raw_invocation_type<Fn(ArgTypes...)>::type does not exist, there shall be no member typedef type. Otherwise:

3.3.3

Logical operator traits

[meta.logical]

This subclause describes type traits for applying logical operators to other type traits.

template<class... B> 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 membervalue which is convertible to bool, is not hidden, and is unambiguously available in the type.

The BaseCharacteristic of a specialization conjunction<B1, …, BN> 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 the last type in the list. [ Note: This means a specialization of conjunction does not necessarily have a BaseCharacteristic of either true_type or false_type.— end note ]

For a specialization conjunction<B1, …, BN> if there is a template type argument Bi with Bi::value == false then instantiating conjunction<B1, …, BN>::value does not require the instantiation of Bj::value for j > i.[ Note: This is analogous to the short-circuiting behavior of &&.— end note ]

template<class... B> 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 membervalue which is convertible to bool, is not hidden, and is unambiguously available in the type.

The BaseCharacteristic of a specialization disjunction<B1, …, BN> 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 the last type in the list. [ Note: This means a specialization of disjunction does not necessarily have a BaseCharacteristic of either true_type or false_type.— end note ]

For a specialization disjunction<B1, …, BN> if there is a template type argument Bi with Bi::value != false then instantiating disjunction<B1, …, BN>::value does not require the instantiation of Bj::value for j > i.[ Note: This is analogous to the short-circuiting behavior of ||.— end note ]

template<class B> struct negation : integral_constant<bool, !B::value> { };

The class template negation forms the logical negation of its template type argument. The type negation<B> is a UnaryTypeTrait with a BaseCharacteristic of integral_constant<bool, !B::value>.

3.3.4

Detection idiom

[meta.detect]

template <class Default, class AlwaysVoid,
          template<class...> class Op, class... Args>
struct DETECTOR { // exposition only
  using value_t = false_type;
  using type = Default;
};

template <class Default, template<class...> class Op, class... Args>
struct DETECTOR<Default, void_t<Op<Args...>>, Op, Args...> { // exposition only
  using value_t = true_type;
  using type = Op<Args...>;
};

template <template<class...> class Op, class... Args>
  using is_detected = typename DETECTOR<nonesuch, void, Op, Args...>::value_t;

template <template<class...> class Op, class... Args>
  using detected_t = typename DETECTOR<nonesuch, void, Op, Args...>::type;

template <class Default, template<class...> class Op, class... Args>
  using detected_or = DETECTOR<Default, void, Op, Args...>;

[ Example:

// archetypal helper alias for a copy assignment operation:
template <class T>
  using copy_assign_t = decltype(declval<T&>() = declval<T const &>());

// plausible implementation for the is_assignable type trait:
template <class T>
  using is_copy_assignable = is_detected<copy_assign_t, T>;

// plausible implementation for an augmented is_assignable type trait
// that also checks the return type:
template <class T>
  using is_canonical_copy_assignable = is_detected_exact<T&, copy_assign_t, T>;

end example ] [ Example:

// archetypal helper alias for a particular type member:
template <class T>
  using diff_t = typename T::difference_type;

// alias the type member, if it exists, otherwise alias ptrdiff_t:
template <class Ptr>
  using difference_type = detected_or_t<ptrdiff_t, diff_t, Ptr>;

end example ]

3.4

Compile-time rational arithmetic

[ratio]

3.5

Time utilities

[time]

3.6

System error support

[syserror]

3.7

Class template propagate_const

[propagate_const]

3.7.1

Class template propagate_const general

[propagate_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.

3.7.2

Header <experimental/propagate_const> synopsis

[propagate_const.synopsis]

namespace std {
  namespace experimental {
  inline namespace fundamentals_v2 {
    template <class T> class propagate_const {
    public:
      typedef remove_reference_t<decltype(*declval<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 <class U>
        see below constexpr propagate_const(propagate_const<U>&& pu);
      template <class U>
        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 <class U>
        constexpr propagate_const& operator=(propagate_const<U>&& pu);
      template <class U>
        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 <class T>
      constexpr bool operator==(const propagate_const<T>& pt, nullptr_t);
    template <class T>
      constexpr bool operator==(nullptr_t, const propagate_const<T>& pu);

    template <class T>
      constexpr bool operator!=(const propagate_const<T>& pt, nullptr_t);
    template <class T>
      constexpr bool operator!=(nullptr_t, const propagate_const<T>& pu);

    template <class T, class U>
      constexpr bool operator==(const propagate_const<T>& pt, const propagate_const<U>& pu);
    template <class T, class U>
      constexpr bool operator!=(const propagate_const<T>& pt, const propagate_const<U>& pu);
    template <class T, class U>
      constexpr bool operator<(const propagate_const<T>& pt, const propagate_const<U>& pu);
    template <class T, class U>
      constexpr bool operator>(const propagate_const<T>& pt, const propagate_const<U>& pu);
    template <class T, class U>
      constexpr bool operator<=(const propagate_const<T>& pt, const propagate_const<U>& pu);
    template <class T, class U>
      constexpr bool operator>=(const propagate_const<T>& pt, const propagate_const<U>& pu);

    template <class T, class U>
      constexpr bool operator==(const propagate_const<T>& pt, const U& u);
    template <class T, class U>
      constexpr bool operator!=(const propagate_const<T>& pt, const U& u);
    template <class T, class U>
      constexpr bool operator<(const propagate_const<T>& pt, const U& u);
    template <class T, class U>
      constexpr bool operator>(const propagate_const<T>& pt, const U& u);
    template <class T, class U>
      constexpr bool operator<=(const propagate_const<T>& pt, const U& u);
    template <class T, class U>
      constexpr bool operator>=(const propagate_const<T>& pt, const U& u);

    template <class T, class U>
      constexpr bool operator==(const T& t, const propagate_const<U>& pu);
    template <class T, class U>
      constexpr bool operator!=(const T& t, const propagate_const<U>& pu);
    template <class T, class U>
      constexpr bool operator<(const T& t, const propagate_const<U>& pu);
    template <class T, class U>
      constexpr bool operator>(const T& t, const propagate_const<U>& pu);
    template <class T, class U>
      constexpr bool operator<=(const T& t, const propagate_const<U>& pu);
    template <class T, class U>
      constexpr bool operator>=(const T& t, const propagate_const<U>& pu);

    // 3.7.10, propagate_const specialized algorithms
    template <class T>
      constexpr void swap(propagate_const<T>& pt, propagate_const<T>& pt2) noexcept(see below);

    // 3.7.11, propagate_const underlying pointer access
    template <class T>
      constexpr const T& get_underlying(const propagate_const<T>& pt) noexcept;
    template <class T>
      constexpr T& get_underlying(propagate_const<T>& pt) noexcept;
  } // inline namespace fundamentals_v2
  } // namespace experimental

  // 3.7.12, propagate_const hash support
  template <class T> struct hash;
  template <class T>
    struct hash<experimental::fundamentals_v2::propagate_const<T>>;

  // 3.7.13, propagate_const comparison function objects
  template <class T> struct equal_to;
  template <class T>
    struct equal_to<experimental::fundamentals_v2::propagate_const<T>>;
  template <class T> struct not_equal_to;
  template <class T>
    struct not_equal_to<experimental::fundamentals_v2::propagate_const<T>>;
  template <class T> struct less;
  template <class T>
    struct less<experimental::fundamentals_v2::propagate_const<T>>;
  template <class T> struct greater;
  template <class T>
    struct greater<experimental::fundamentals_v2::propagate_const<T>>;
  template <class T> struct less_equal;
  template <class T>
    struct less_equal<experimental::fundamentals_v2::propagate_const<T>>;
  template <class T> struct greater_equal;
  template <class T>
    struct greater_equal<experimental::fundamentals_v2::propagate_const<T>>;
} // namespace std

3.7.3

propagate_const requirements on T

[propagate_const.requirements]

T shall be an object pointer type or a class type for whichdecltype(*declval<T&>()) 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.

[ Note: propagate_const<const int*> is well-formed— end note ]

3.7.3.1

propagate_const requirements on class type T

[propagate_const.class_type_requirements]

If T is class type then it shall satisfy the following requirements. In this sub-clauset 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.

Table 4 — Requirements on class types T

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

3.7.4

propagate_const constructors

[propagate_const.ctor]

[ Note: The following constructors are conditionally specified asexplicit. This is typically implemented by declaring two such constructors, of which at most one participates in overload resolution.— end note ]

template <class U>
see below constexpr propagate_const(propagate_const<U>&& pu);

Remarks:

This constructor shall not participate in overload resolution unlessis_constructible_v<T, U&&>. The constructor is specified as explicit if and only if!is_convertible_v<U&&, T>.

Effects:

Initializes t_ as if direct-non-list-initializing an object of type T with the expression std::move(pu.t_).

template <class U>
see below constexpr propagate_const(U&& u);

Remarks:

This constructor shall not participate in overload resolution unlessis_constructible_v<T, U&&> and decay_t<U> is not a specialization of propagate_const. The constructor is specified as explicit if and only if!is_convertible_v<U&&, T>.

Effects:

Initializes t_ as if direct-non-list-initializing an object of type T with the expression std::forward<U>(u).

3.7.5

propagate_const assignment

[propagate_const.assignment]

template <class U>
constexpr propagate_const& operator=(propagate_const<U>&& pu);

Remarks:

This function shall not participate in overload resolution unlessU is implicitly convertible to T.

Effects:

t_ = std::move(pu.t_).

Returns:

*this.

template <class U>
constexpr propagate_const& operator=(U&& u);

Remarks:

This function shall not participate in overload resolution unlessU is implicitly convertible to T anddecay_t<U> is not a specialization of propagate_const.

Effects:

t_ = std::forward<U>(u).

Returns:

*this.

3.7.6

propagate_const const observers

[propagate_const.const_observers]

explicit constexpr operator bool() const;

Returns:

(bool)t_.

constexpr const element_type* operator->() const;

Requires:

get() != nullptr.

Returns:

get().

constexpr operator const element_type*() const;

Returns:

get().

Remarks:

This function shall not participate in overload resolution unlessT is an object pointer type or has an implicit conversion to const element_type*.

constexpr const element_type& operator*() const;

Requires:

get() != nullptr.

Returns:

*get().

constexpr const element_type* get() const;

Returns:

t_ if T is an object pointer type, otherwise t_.get().

3.7.7

propagate_const non-const observers

[propagate_const.non_const_observers]

constexpr element_type* operator->();

Requires:

get() != nullptr.

Returns:

get().

constexpr operator element_type*();

Returns:

get().

Remarks:

This function shall not participate in overload resolution unlessT is an object pointer type or has an implicit conversion to element_type*.

constexpr element_type& operator*();

Requires:

get() != nullptr.

Returns:

*get().

constexpr element_type* get();

Returns:

t_ if T is an object pointer type, otherwise t_.get().

3.7.8

propagate_const modifiers

[propagate_const.modifiers]

constexpr void swap(propagate_const& pt) noexcept(see below);

The constant-expression in the exception-specification is noexcept(swap(t_, pt.t_)).

Effects:

swap(t_, pt.t_).

3.7.9

propagate_const relational operators

[propagate_const.relational]

template <class T>
constexpr bool operator==(const propagate_const<T>& pt, nullptr_t);

Returns:

pt.t_ == nullptr.

template <class T>
constexpr bool operator==(nullptr_t, const propagate_const<T>& pt);

Returns:

nullptr == pt.t_.

template <class T>
constexpr bool operator!=(const propagate_const<T>& pt, nullptr_t);

Returns:

pt.t_ != nullptr.

template <class T>
constexpr bool operator!=(nullptr_t, const propagate_const<T>& pt);

Returns:

nullptr != pt.t_.

template <class T, class U>
constexpr bool operator==(const propagate_const<T>& pt, const propagate_const<U>& pu);

Returns:

pt.t_ == pu.t_.

template <class T, class U>
constexpr bool operator!=(const propagate_const<T>& pt, const propagate_const<U>& pu);

Returns:

pt.t_ != pu.t_.

template <class T, class U>
constexpr bool operator<(const propagate_const<T>& pt, const propagate_const<U>& pu);

Returns:

pt.t_ < pu.t_.

template <class T, class U>
constexpr bool operator>(const propagate_const<T>& pt, const propagate_const<U>& pu);

Returns:

pt.t_ > pu.t_.

template <class T, class U>
constexpr bool operator<=(const propagate_const<T>& pt, const propagate_const<U>& pu);

Returns:

pt.t_ <= pu.t_.

template <class T, class U>
constexpr bool operator>=(const propagate_const<T>& pt, const propagate_const<U>& pu);

Returns:

pt.t_ >= pu.t_.

template <class T, class U>
constexpr bool operator==(const propagate_const<T>& pt, const U& u);

Returns:

pt.t_ == u.

template <class T, class U>
constexpr bool operator!=(const propagate_const<T>& pt, const U& u);

Returns:

pt.t_ != u.

template <class T, class U>
constexpr bool operator<(const propagate_const<T>& pt, const U& u);

Returns:

pt.t_ < u.

template <class T, class U>
constexpr bool operator>(const propagate_const<T>& pt, const U& u);

Returns:

pt.t_ > u.

template <class T, class U>
constexpr bool operator<=(const propagate_const<T>& pt, const U& u);

Returns:

pt.t_ <= u.

template <class T, class U>
constexpr bool operator>=(const propagate_const<T>& pt, const U& u);

Returns:

pt.t_ >= u.

template <class T, class U>
constexpr bool operator==(const T& t, const propagate_const<U>& pu);

Returns:

t == pu.t_.

template <class T, class U>
constexpr bool operator!=(const T& t, const propagate_const<U>& pu);

Returns:

t != pu.t_.

template <class T, class U>
constexpr bool operator<(const T& t, const propagate_const<U>& pu);

Returns:

t < pu.t_.

template <class T, class U>
constexpr bool operator>(const T& t, const propagate_const<U>& pu);

Returns:

t > pu.t_.

template <class T, class U>
constexpr bool operator<=(const T& t, const propagate_const<U>& pu);

Returns:

t <= pu.t_.

template <class T, class U>
constexpr bool operator>=(const T& t, const propagate_const<U>& pu);

Returns:

t >= pu.t_.

3.7.10

propagate_const specialized algorithms

[propagate_const.algorithms]

template <class T>
constexpr void swap(propagate_const<T>& pt1, propagate_const<T>& pt2) noexcept(see below);

The constant-expression in the exception-specification is noexcept(swap(pt1.t_, pt2.t_)).

Effects:

swap(pt1.t_, pt2.t_).

3.7.11

propagate_const underlying pointer access

[propagate_const.underlying]

Access 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 <class T>
constexpr const T& get_underlying(const propagate_const<T>& pt) noexcept;

Returns:

a reference to the underlying object pointer type.

template <class T>
constexpr T& get_underlying(propagate_const<T>& pt) noexcept;

Returns:

a reference to the underlying object pointer type.

3.7.12

propagate_const hash support

[propagate_const.hash]

template <class T>
struct hash<experimental::fundamentals_v2::propagate_const<T>>;

For an object p of type propagate_const<T>,hash<experimental::fundamentals_v2::propagate_const<T>>()(p) shall evaluate to the same value as hash<T>()(p.t_).

Requires:

The specialization hash<T> shall be well-formed and well-defined, and shall meet the requirements of class template hash.

3.7.13

propagate_const comparison function objects

[propagate_const.comparison_function_objects]

template <class T>
struct equal_to<experimental::fundamentals_v2::propagate_const<T>>;

For objects p, q of type propagate_const<T>,equal_to<experimental::fundamentals_v2::propagate_const<T>>()(p, q) shall evaluate to the same value as equal_to<T>()(p.t_, q.t_).

Requires:

The specialization equal_to<T> shall be well-formed and well-defined.

template <class T>
struct not_equal_to<experimental::fundamentals_v2::propagate_const<T>>;

For objects p, q of type propagate_const<T>,not_equal_to<experimental::fundamentals_v2::propagate_const<T>>()(p, q) shall evaluate to the same value as not_equal_to<T>()(p.t_, q.t_).

Requires:

The specialization not_equal_to<T> shall be well-formed and well-defined.

template <class T>
struct less<experimental::fundamentals_v2::propagate_const<T>>;

For objects p, q of type propagate_const<T>,less<experimental::fundamentals_v2::propagate_const<T>>()(p, q) shall evaluate to the same value as less<T>()(p.t_, q.t_).

Requires:

The specialization less<T> shall be well-formed and well-defined.

template <class T>
struct greater<experimental::fundamentals_v2::propagate_const<T>>;

For objects p, q of type propagate_const<T>,greater<experimental::fundamentals_v2::propagate_const<T>>()(p, q) shall evaluate to the same value as greater<T>()(p.t_, q.t_).

Requires:

The specialization greater<T> shall be well-formed and well-defined.

template <class T>
struct less_equal<experimental::fundamentals_v2::propagate_const<T>>;

For objects p, q of type propagate_const<T>,less_equal<experimental::fundamentals_v2::propagate_const<T>>()(p, q) shall evaluate to the same value as less_equal<T>()(p.t_, q.t_).

Requires:

The specialization less_equal<T> shall be well-formed and well-defined.

template <class T>
struct greater_equal<experimental::fundamentals_v2::propagate_const<T>>;

For objects p, q of type propagate_const<T>,greater_equal<experimental::fundamentals_v2::propagate_const<T>>()(p, q) shall evaluate to the same value as greater_equal<T>()(p.t_, q.t_).

Requires:

The specialization greater_equal<T> shall be well-formed and well-defined.

4

Function objects

[func]

4.2

Class template function

[func.wrap.func]

The specification of all declarations within this sub-clause 4.2 and its sub-clauses are the same as the corresponding declarations, as specified in C++14 §20.9.11.2, unless explicitly specified otherwise. [ Note: std::experimental::function usesstd::bad_function_call, there is no additional type std::experimental::bad_function_callend note ] .

namespace std {
  namespace experimental {
  inline namespace fundamentals_v2 {

    template<class> class function; // undefined

    template<class R, class... ArgTypes>
    class function<R(ArgTypes...)> {
    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<class F> function(F);
      template<class A> function(allocator_arg_t, const A&) noexcept;
      template<class A> function(allocator_arg_t, const A&,
        nullptr_t) noexcept;
      template<class A> function(allocator_arg_t, const A&,
        const function&);
      template<class A> function(allocator_arg_t, const A&,
        function&&);
      template<class F, class A> function(allocator_arg_t, const A&, F);

      function& operator=(const function&);
      function& operator=(function&&);
      function& operator=(nullptr_t) noexcept;
      template<class F> function& operator=(F&&);
      template<class F> function& operator=(reference_wrapper<F>);

      ~function();

      void swap(function&);

      explicit operator bool() const noexcept;

      R operator()(ArgTypes...) const;

      const type_info& target_type() const noexcept;
      template<class T> T* target() noexcept;
      template<class T> const T* target() const noexcept;

      pmr::memory_resource* get_memory_resource();
    };

    template <class R, class... ArgTypes>
    bool operator==(const function<R(ArgTypes...)>&, nullptr_t) noexcept;
    template <class R, class... ArgTypes>
    bool operator==(nullptr_t, const function<R(ArgTypes...)>&) noexcept;

    template <class R, class... ArgTypes>
    bool operator!=(const function<R(ArgTypes...)>&, nullptr_t) noexcept;
    template <class R, class... ArgTypes>
    bool operator!=(nullptr_t, const function<R(ArgTypes...)>&) noexcept;

    template <class R, class... ArgTypes>
    void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&);

  } // namespace fundamentals_v2
  } // namespace experimental

  template <class R, class... ArgTypes, class Alloc>
  struct uses_allocator<experimental::function<R(ArgTypes...)>, Alloc>
    : true_type { };

} // namespace std

4.2.1

function construct/copy/destroy

[func.wrap.func.con]

When a function constructor that takes a first argument of type allocator_arg_t is invoked, the second argument is treated as a type-erased allocator (8.3). If the constructor moves or makes a copy of a function object (C++14 §20.9), including an instance of the experimental::function class template, then that move or copy is performed by using-allocator construction with allocator get_memory_resource().

In the following descriptions, let _ALLOCATOROF_(f) be the allocator specified in the construction of function f, or allocator<char>() if no allocator was specified.

function& operator=(const function& f);

Effects:

function(allocator_arg, _ALLOCATOROF_(*this), f).swap(*this);

Returns:

*this.

function& operator=(function&& f);

Effects:

function(allocator_arg, _ALLOCATOROF_(*this), std::move(f)).swap(*this);

Returns:

*this.

function& operator=(nullptr_t) noexcept;

Effects:

If *this != nullptr, destroys the target of this.

Postconditions:

!(*this). The memory resource returned by get_memory_resource() after the assignment is equivalent to the memory resource before the assignment.[ Note: the address returned by get_memory_resource() might change— end note ]

Returns:

*this.

template<class F> function& operator=(F&& f);

Effects:

function(allocator_arg, _ALLOCATOROF_(*this), std::forward<F>(f)).swap(*this);

Returns:

*this.

Remarks:

This assignment operator shall not participate in overload resolution unlessdeclval<decay_t<F>&>() is Callable (C++14 §20.9.11.2) for argument types ArgTypes... and return type R.

template<class F> function& operator=(reference_wrapper<F> f);

Effects:

function(allocator_arg, _ALLOCATOROF_(*this), f).swap(*this);

Returns:

*this.

4.2.2

function modifiers

[func.wrap.func.mod]

void swap(function& other);

Requires:

*this->get_memory_resource() == *other.get_memory_resource().

Effects:

Interchanges the targets of *this and other.

Remarks:

The allocators of *this and other are not interchanged.

4.3

Searchers

[func.searchers]

This sub-clause provides function object types (C++14 §20.9) for operations that search for a sequence [pat_first, pat_last) in another sequence [first, last) that is provided to the object's function call operator. The first sequence (the pattern to be searched for) is provided to the object's constructor, and the second (the sequence to be searched) is provided to the function call operator.

Each specialization of a class template specified in this sub-clause 4.3 shall meet the CopyConstructible and CopyAssignable requirements. Template parameters named ForwardIterator, ForwardIterator1, ForwardIterator2, RandomAccessIterator, RandomAccessIterator1, RandomAccessIterator2, and BinaryPredicate of templates specified in this sub-clause 4.3 shall meet the same requirements and semantics as specified in C++14 §25.1. Template parameters named Hash shall meet the requirements as specified in C++14 §17.6.3.4.

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

4.3.1

Class template default_searcher

[func.searchers.default]

template<class ForwardIterator1, class BinaryPredicate = equal_to<>>
class default_searcher {
public:
  default_searcher(ForwardIterator1 pat_first, ForwardIterator1 pat_last,
                   BinaryPredicate pred = BinaryPredicate());

  template<class ForwardIterator2>
  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());

Effects:

Constructs a default_searcher object, initializing pat_first_ with pat_first, pat_last_ with pat_last, and pred_ with pred.

Throws:

Any exception thrown by the copy constructor of BinaryPredicate or ForwardIterator1.

template<class ForwardIterator2>
ForwardIterator2 operator()(ForwardIterator2 first, ForwardIterator2 last) const;

Effects:

Equivalent to return std::search(first, last, pat_first_, pat_last_, pred_);

4.3.1.1

default_searcher creation functions

[func.searchers.default.creation]

template<class ForwardIterator, class BinaryPredicate = equal_to<>>
default_searcher<ForwardIterator, BinaryPredicate>
make_default_searcher(ForwardIterator pat_first, ForwardIterator pat_last,
                      BinaryPredicate pred = BinaryPredicate());

Effects:

Equivalent to return default_searcher<ForwardIterator, BinaryPredicate>(pat_first, pat_last, pred);

4.3.2

Class template boyer_moore_searcher

[func.searchers.boyer_moore]

template<class RandomAccessIterator1,
         class Hash = hash<typename iterator_traits<RandomAccessIterator1>::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<class RandomAccessIterator2>
  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());

Requires:

The value type of RandomAccessIterator1 shall meet the DefaultConstructible, CopyConstructible, and CopyAssignable requirements.

Requires:

For any two values A and B of the type iterator_traits<RandomAccessIterator1>::value_type, if pred(A,B)==true, then hf(A)==hf(B) shall be true.

Effects:

Constructs a boyer_moore_searcher object, initializing pat_first_ with pat_first, pat_last_ with pat_last, hash_ with hf, and pred_ with pred.

Throws:

Any exception thrown by the copy constructor of 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<class RandomAccessIterator2>
RandomAccessIterator2 operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const;

Requires:

RandomAccessIterator1 and RandomAccessIterator2 shall have the same value type.

Effects:

Finds a subsequence of equal values in a sequence.

Returns:

The first iterator i in the range [first, last - (pat_last_ - pat_first_)) such that for every non-negative integer 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_) is empty, otherwise returns last if no such iterator is found.

Complexity:

At most (last - first) * (pat_last_ - pat_first_) applications of the predicate.

4.3.2.1

boyer_moore_searcher creation functions

[func.searchers.boyer_moore.creation]

template<class RandomAccessIterator,
class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
class BinaryPredicate = equal_to<>>
  boyer_moore_searcher<RandomAccessIterator, Hash, BinaryPredicate>
  make_boyer_moore_searcher(RandomAccessIterator pat_first, RandomAccessIterator pat_last,
                            Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());

Effects:

Equivalent to return boyer_moore_searcher<RandomAccessIterator, Hash, BinaryPredicate>(pat_first, pat_last, hf, pred);

4.3.3

Class template boyer_moore_horspool_searcher

[func.searchers.boyer_moore_horspool]


template<class RandomAccessIterator1,
         class Hash = hash<typename iterator_traits<RandomAccessIterator1>::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<class RandomAccessIterator2>
  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());

Requires:

The value type of RandomAccessIterator1 shall meet the DefaultConstructible, CopyConstructible, and CopyAssignable requirements.

Requires:

For any two values A and B of the type iterator_traits<RandomAccessIterator1>::value_type, if pred(A,B)==true, then hf(A)==hf(B) shall be true.

Effects:

Constructs a boyer_moore_horspool_searcher object, initializing pat_first_ with pat_first,pat_last_ with pat_last, hash_ with hf, and pred_ with pred.

Throws:

Any exception thrown by the copy constructor of 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<class RandomAccessIterator2>
RandomAccessIterator2 operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const;

Requires:

RandomAccessIterator1 and RandomAccessIterator2 shall have the same value type.

Effects:

Finds a subsequence of equal values in a sequence.

Returns:

The first iterator i in the range [first, last - (pat_last_ - pat_first_)) such that for every non-negative integer 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_) is empty, otherwise returns last if no such iterator is found.

Complexity:

At most (last - first) * (pat_last_ - pat_first_) applications of the predicate.

4.3.3.1

boyer_moore_horspool_searcher creation functions

[func.searchers.boyer_moore_horspool.creation]

template<class RandomAccessIterator,
         class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
         class BinaryPredicate = equal_to<>>
boyer_moore_horspool_searcher<RandomAccessIterator, Hash, BinaryPredicate>
make_boyer_moore_horspool_searcher(
    RandomAccessIterator pat_first, RandomAccessIterator pat_last,
    Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());

Effects:

Equivalent to return boyer_moore_horspool_searcher<RandomAccessIterator, Hash, BinaryPredicate>(pat_first, pat_last, hf, pred);

4.4

Function template not_fn

[func.not_fn]

template <class F> unspecified not_fn(F&& f);

In the text that follows:

Requires:

is_constructible<FD, F>::value shall be true.fd shall be a callable object (C++14 §20.9.1).

Returns:

A forwarding call wrapper fn such that the expression fn(a1, a2, ..., aN) is equivalent to !_INVOKE_(fd, a1, a2, ..., aN) (C++14 §20.9.2).

Throws:

Nothing unless the construction of fd throws an exception.

Remarks:

The return type shall satisfy the requirements of MoveConstructible. If FD satisfies the requirements of CopyConstructible, then the return type shall satisfy the requirements of CopyConstructible.[ Note: This implies that FD is MoveConstructible.— end note ]

[ Note: Function template not_fn can usually provide a better solution than using the negators not1 and not2end note ]

5

Optional objects

[optional]

5.1

In general

[optional.general]

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.

5.2

Header <experimental/optional> synopsis

[optional.synop]

namespace std {
  namespace experimental {
  inline namespace fundamentals_v2 {

    // 5.3, optional for object types
    template <class T> 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 <class T>
      constexpr bool operator==(const optional<T>&, const optional<T>&);
    template <class T>
      constexpr bool operator!=(const optional<T>&, const optional<T>&);
    template <class T>
      constexpr bool operator<(const optional<T>&, const optional<T>&);
    template <class T>
      constexpr bool operator>(const optional<T>&, const optional<T>&);
    template <class T>
      constexpr bool operator<=(const optional<T>&, const optional<T>&);
    template <class T>
      constexpr bool operator>=(const optional<T>&, const optional<T>&);

    // 5.8, Comparison with nullopt
    template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
    template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
    template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept;
    template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept;
    template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
    template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
    template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept;
    template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept;
    template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;
    template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;
    template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept;
    template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept;

    // 5.9, Comparison with T
    template <class T> constexpr bool operator==(const optional<T>&, const T&);
    template <class T> constexpr bool operator==(const T&, const optional<T>&);
    template <class T> constexpr bool operator!=(const optional<T>&, const T&);
    template <class T> constexpr bool operator!=(const T&, const optional<T>&);
    template <class T> constexpr bool operator<(const optional<T>&, const T&);
    template <class T> constexpr bool operator<(const T&, const optional<T>&);
    template <class T> constexpr bool operator<=(const optional<T>&, const T&);
    template <class T> constexpr bool operator<=(const T&, const optional<T>&);
    template <class T> constexpr bool operator>(const optional<T>&, const T&);
    template <class T> constexpr bool operator>(const T&, const optional<T>&);
    template <class T> constexpr bool operator>=(const optional<T>&, const T&);
    template <class T> constexpr bool operator>=(const T&, const optional<T>&);

    // 5.10, Specialized algorithms
    template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below);
    template <class T> constexpr optional<see below> make_optional(T&&);

  } // namespace fundamentals_v2
  } // namespace experimental

  // 5.11, Hash support
  template <class T> struct hash;
  template <class T> struct hash<experimental::optional<T>>;

} // 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.

5.3

optional for object types

[optional.object]

template <class T>
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 <class... Args> constexpr explicit optional(in_place_t, Args&&...);
  template <class U, class... Args>
    constexpr explicit optional(in_place_t, initializer_list<U>, Args&&...);
  template <class U> constexpr optional(U&&);
  template <class U> constexpr optional(const optional<U>&);
  template <class U> constexpr optional(optional<U>&&);

  // 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 <class U> optional& operator=(U&&);
  template <class U> optional& operator=(const optional<U>&);
  template <class U> optional& operator=(optional<U>&&);
  template <class... Args> void emplace(Args&&...);
  template <class U, class... Args>
    void emplace(initializer_list<U>, 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 <class U> constexpr T value_or(U&&) const &;
  template <class U> constexpr T value_or(U&&) &&;

private:
  T*   val;  // exposition only
};

Any instance of optional<T> at any given time either contains a value or does not contain a value. When an instance of optional<T> 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<T> storage suitably aligned for the type T. It is implementation-defined whether over-aligned types are supported (C++14 §3.11). When an object of type optional<T> 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<T> 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).

5.3.1

Constructors

[optional.object.ctor]

constexpr optional() noexcept;constexpr optional(nullopt_t) noexcept;

Postconditions:

*this does not contain a value.

Remarks:

No contained value is initialized. For every object type T these constructors shall be constexpr constructors (C++14 §7.1.5).

optional(const optional<T>& rhs);

Requires:

is_copy_constructible_v<T> is true.

Effects:

If rhs contains a value, initializes the contained value as if direct-non-list-initializing an object of type T with the expression *rhs.

Postconditions:

bool(rhs) == bool(*this).

Throws:

Any exception thrown by the selected constructor of T.

optional(optional<T>&& rhs) noexcept(see below);

Requires:

is_move_constructible_v<T> is true.

Effects:

If 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.

Postconditions:

bool(rhs) == bool(*this).

Throws:

Any exception thrown by the selected constructor of T.

Remarks:

The expression inside noexcept is equivalent to:

is_nothrow_move_constructible_v<T>
constexpr optional(const T& v);

Requires:

is_copy_constructible_v<T> is true.

Effects:

Initializes the contained value as if direct-non-list-initializing an object of type T with the expression v.

Postconditions:

*this contains a value.

Throws:

Any exception thrown by the selected constructor of T.

Remarks:

If T's selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor.

constexpr optional(T&& v);

Requires:

is_move_constructible_v<T> is true.

Effects:

Initializes the contained value as if direct-non-list-initializing an object of type T with the expression std::move(v).

Postconditions:

*this contains a value.

Throws:

Any exception thrown by the selected constructor of T.

Remarks:

If T's selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor.

template <class... Args> constexpr explicit optional(in_place_t, Args&&... args);

Requires:

is_constructible_v<T, Args&&...> is true.

Effects:

Initializes the contained value as if direct-non-list-initializing an object of type T with the arguments std::forward<Args>(args)....

Postconditions:

*this contains a value.

Throws:

Any exception thrown by the selected constructor of T.

Remarks:

If T's constructor selected for the initialization is a constexpr constructor, this constructor shall be a constexpr constructor.

template <class U, class... Args>
constexpr explicit optional(in_place_t, initializer_list<U> il, Args&&... args);

Requires:

is_constructible_v<T, initializer_list<U>&, Args&&...> is true.

Effects:

Initializes the contained value as if direct-non-list-initializing an object of type T with the arguments il, std::forward<Args>(args)....

Postconditions:

*this contains a value.

Throws:

Any exception thrown by the selected constructor of T.

Remarks:

The function shall not participate in overload resolution unless is_constructible_v<T, initializer_list<U>&, Args&&...> is true. If T's constructor selected for the initialization is a constexpr constructor, this constructor shall be a constexpr constructor.

[ Note: The following constructors are conditionally specified as explicit. This is typically implemented by declaring two such constructors, of which at most one participates in overload resolution.— end note ]

template <class U>
constexpr optional(U&& v);

Effects:

Initializes the contained value as if direct-non-list-initializing an object of type T with the expression std::forward<U>(v).

Postconditions:

*this contains a value.

Throws:

Any exception thrown by the selected constructor of T.

Remarks:

If T's selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor. This constructor shall not participate in overload resolution unless is_constructible_v<T, U&&> is true and U is not the same type as T. The constructor is explicit if and only if is_convertible_v<U&&, T> is false.

template <class U>
constexpr optional(const optional<U>& rhs);

Effects:

If rhs contains a value, initializes the contained value as if direct-non-list-initializing an object of type T with the expression *rhs.

Postconditions:

bool(rhs) == bool(*this).

Throws:

Any exception thrown by the selected constructor of T.

Remarks:

If T's selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor. This constructor shall not participate in overload resolution unless is_constructible_v<T, const U&> is true, is_same<decay_t<U>, T> is false, is_constructible_v<T, const optional<U>&> is false and is_convertible_v<const optional<U>&, T> is false. The constructor is explicit if and only if is_convertible_v<const U&, T> is false.

template <class U>
constexpr optional(optional<U>&& rhs);

Effects:

If 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.

Postconditions:

bool(rhs) == bool(*this).

Throws:

Any exception thrown by the selected constructor of T.

Remarks:

If T's selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor. This constructor shall not participate in overload resolution unless is_constructible_v<T, U&&> is true, is_same<decay_t<U>, T> is false, is_constructible_v<T, optional<U>&&> is false and is_convertible_v<optional<U>&&, T> is false and U is not the same type as T. The constructor is explicit if and only if is_convertible_v<U&&, T> is false.

5.3.2

Destructor

[optional.object.dtor]

~optional();

Effects:

If is_trivially_destructible_v<T> != true and *this contains a value, calls val->T::~T().

Remarks:

If is_trivially_destructible_v<T> == true then this destructor shall be a trivial destructor.

5.3.3

Assignment

[optional.object.assign]

optional<T>& operator=(nullopt_t) noexcept;

Effects:

If *this contains a value, calls val->T::~T() to destroy the contained value; otherwise no effect.

Returns:

*this.

Postconditions:

*this does not contain a value.

optional<T>& operator=(const optional<T>& rhs);

Requires:

is_copy_constructible_v<T> is true and is_copy_assignable_v<T> is true.

Effects:

Table 5 — optional::operator=(const optional&) effects

*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

Returns:

*this.

Postconditions:

bool(rhs) == bool(*this).

Remarks:

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 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<T>& operator=(optional<T>&& rhs) noexcept(see below);

Requires:

is_move_constructible_v<T> is true and is_move_assignable_v<T> is true.

Effects:

The result of the expression bool(rhs) remains unchanged.

Table 6 — optional::operator=(optional&&) effects

*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

Returns:

*this.

Postconditions:

bool(rhs) == bool(*this).

Remarks:

The expression inside noexcept is equivalent to:

is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T>

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 <class U> optional<T>& operator=(U&& v);

Requires:

is_constructible_v<T, U> is true and is_assignable_v<T&, U> is true.

Effects:

If *this contains a value, assigns std::forward<U>(v) to the contained value; otherwise initializes the contained value as if direct-non-list-initializing object of type T with std::forward<U>(v).

Returns:

*this.

Postconditions:

*this contains a value.

Remarks:

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 unlessdecay_t<U> is not nullopt_t and decay_t<U> is not a specialization of optional.

template <class U> optional<T>& operator=(const optional<U>& rhs);

Requires:

is_constructible_v<T, const U&> is true and is_assignable_v<T&, const U&> is true.

Effects:

Table 7 — optional::operator=(const optional&) effects

*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

Returns:

*this.

Postconditions:

bool(rhs) == bool(*this).

Remarks:

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 *rhs.val 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 *rhs.val is determined by the exception safety guarantee of T's assignment. The function shall not participate in overload resolution unless is_same_v<decay_t<U>, T> is false.

template <class U> optional<T>& operator=(optional<U>&& rhs);

Requires:

is_constructible_v<T, U> is true and is_assignable_v<T&, U> is true.

Effects:

The result of the expression bool(rhs) remains unchanged.

Table 8 — optional::operator=(optional&&) effects

*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

Returns:

*this.

Postconditions:

bool(rhs) == bool(*this).

Remarks:

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 *rhs.val 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 *rhs.val is determined by the exception safety guarantee of T's assignment. The function shall not participate in overload resolution unless is_same_v<decay_t<U>, T> is false.

template <class... Args> void emplace(Args&&... args);

Requires:

is_constructible_v<T, Args&&...> is true.

Effects:

Calls *this = nullopt. Then initializes the contained value as if direct-non-list-initializing an object of type T with the arguments std::forward<Args>(args)....

Postconditions:

*this contains a value.

Throws:

Any exception thrown by the selected constructor of T.

Remarks:

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.

template <class U, class... Args> void emplace(initializer_list<U> il, Args&&... args);

Effects:

Calls *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>(args)....

Postconditions:

*this contains a value.

Throws:

Any exception thrown by the selected constructor of T.

Remarks:

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<T, initializer_list<U>&, Args&&...> is true.

5.3.4

Swap

[optional.object.swap]

void swap(optional<T>& rhs) noexcept(see below);

Requires:

Lvalues of type T shall be swappable and is_move_constructible_v<T> is true.

Effects:

Table 9 — optional::swap(optional&) effects

*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

Throws:

Any exceptions that the expressions in the Effects element throw.

Remarks:

The expression inside noexcept is equivalent to:

is_nothrow_move_constructible_v<T> && noexcept(swap(declval<T&>(), declval<T&>()))

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.

5.3.5

Observers

[optional.object.observe]

constexpr T const* operator->() const;constexpr T* operator->();

Requires:

*this contains a value.

Returns:

val.

Throws:

Nothing.

Remarks:

Unless T is a user-defined type with overloaded unary operator&, these functions shall be constexpr functions.

constexpr T const& operator*() const &;constexpr T& operator*() &;

Requires:

*this contains a value.

Returns:

*val.

Throws:

Nothing.

Remarks:

These functions shall be constexpr functions.

constexpr T&& operator*() &&;constexpr const T&& operator*() const &&;

Requires:

*this contains a value.

Effects:

Equivalent to return std::move(*val);

constexpr explicit operator bool() const noexcept;

Returns:

true if and only if *this contains a value.

Remarks:

This function shall be a constexpr function.

constexpr T const& value() const &;constexpr T& value() &;

Effects:

Equivalent to return bool(*this) ? *val : throw bad_optional_access();

constexpr T&& value() &&;constexpr const T&& value() const &&;

Effects:

Equivalent to return bool(*this) ? std::move(*val) : throw bad_optional_access();

template <class U> constexpr T value_or(U&& v) const &;

Effects:

Equivalent to return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));

Remarks:

If is_copy_constructible_v<T> && is_convertible_v<U&&, T> is false, the program is ill-formed.

template <class U> T value_or(U&& v) &&;

Effects:

Equivalent to return bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(v));

Remarks:

If is_move_constructible_v<T> && is_convertible_v<U&&, T> is false, the program is ill-formed.

5.4

In-place construction

[optional.inplace]

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<T> 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.

5.5

No-value state indicator

[optional.nullopt]

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<T> 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.

5.6

Class bad_optional_access

[optional.bad_optional_access]

class 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();

Effects:

Constructs an object of class bad_optional_access.

Postconditions:

what() returns an implementation-defined NTBS.

5.7

Relational operators

[optional.relops]

template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y);

Requires:

T shall meet the requirements of EqualityComparable.

Returns:

If bool(x) != bool(y), false; otherwise if bool(x) == false, true; otherwise *x == *y.

Remarks:

Specializations of this function template, for which *x == *y is a core constant expression, shall be constexpr functions.

template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y);

Returns:

!(x == y).

template <class T> constexpr bool operator<(const optional<T>& x, const optional<T>& y);

Requires:

*x < *y shall be well-formed and its result shall be convertible to bool.

Returns:

If !y, false; otherwise, if !x, true; otherwise *x < *y.

Remarks:

Specializations of this function template, for which *x < *y is a core constant expression, shall be constexpr functions.

template <class T> constexpr bool operator>(const optional<T>& x, const optional<T>& y);

Returns:

y < x.

template <class T> constexpr bool operator<=(const optional<T>& x, const optional<T>& y);

Returns:

!(y < x).

template <class T> constexpr bool operator>=(const optional<T>& x, const optional<T>& y);

Returns:

!(x < y).

5.8

Comparison with nullopt

[optional.nullops]

template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept;template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept;

Returns:

!x.

template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept;template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept;

Returns:

bool(x).

template <class T> constexpr bool operator<(const optional<T>& x, nullopt_t) noexcept;

Returns:

false.

template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept;

Returns:

bool(x).

template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept;

Returns:

!x.

template <class T> constexpr bool operator<=(nullopt_t, const optional<T>& x) noexcept;

Returns:

true.

template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept;

Returns:

bool(x).

template <class T> constexpr bool operator>(nullopt_t, const optional<T>& x) noexcept;

Returns:

false.

template <class T> constexpr bool operator>=(const optional<T>& x, nullopt_t) noexcept;

Returns:

true.

template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept;

Returns:

!x.

5.9

Comparison with T

[optional.comp_with_t]

template <class T> constexpr bool operator==(const optional<T>& x, const T& v);

Returns:

bool(x) ? *x == v : false.

template <class T> constexpr bool operator==(const T& v, const optional<T>& x);

Returns:

bool(x) ? v == *x : false.

template <class T> constexpr bool operator!=(const optional<T>& x, const T& v);

Returns:

bool(x) ? !(*x == v) : true.

template <class T> constexpr bool operator!=(const T& v, const optional<T>& x);

Returns:

bool(x) ? !(v == *x) : true.

template <class T> constexpr bool operator<(const optional<T>& x, const T& v);

Returns:

bool(x) ? *x < v : true.

template <class T> constexpr bool operator<(const T& v, const optional<T>& x);

Returns:

bool(x) ? v < *x : false.

template <class T> constexpr bool operator<=(const optional<T>& x, const T& v);

Returns:

!(x > v).

template <class T> constexpr bool operator<=(const T& v, const optional<T>& x);

Returns:

!(v > x).

template <class T> constexpr bool operator>(const optional<T>& x, const T& v);

Returns:

bool(x) ? v < *x : false.

template <class T> constexpr bool operator>(const T& v, const optional<T>& x);

Returns:

bool(x) ? *x < v : true.

template <class T> constexpr bool operator>=(const optional<T>& x, const T& v);

Returns:

!(x < v).

template <class T> constexpr bool operator>=(const T& v, const optional<T>& x);

Returns:

!(v < x).

5.10

Specialized algorithms

[optional.specalg]

template <class T> void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y)));

Effects:

Calls x.swap(y).

template <class T> constexpr optional<decay_t<T>> make_optional(T&& v);

Returns:

optional<decay_t<T>>(std::forward<T>(v)).

5.11

Hash support

[optional.hash]

template <class T> struct hash<experimental::optional<T>>;

Requires:

The template specialization hash<T> shall meet the requirements of class template hash (C++14 §20.9.12). The template specialization hash<optional<T>> shall meet the requirements of class template hash. For an object o of type optional<T>, if bool(o) == true,hash<optional<T>>()(o) shall evaluate to the same value as hash<T>()(*o); otherwise it evaluates to an unspecified value.

6

Class any

[any]

This section describes components that C++ programs may use to perform operations on objects of a discriminated type.

[ Note: The discriminated type may contain values of different types but does not attempt conversion between them, i.e. 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 ]

6.1

Header <experimental/any> synopsis

[any.synop]

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 <class ValueType>
      any(ValueType&& value);

    ~any();

    // 6.3.2, any assignments
    any& operator=(const any& rhs);
    any& operator=(any&& rhs) noexcept;

    template <class ValueType>
      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<class ValueType>
    ValueType any_cast(const any& operand);
  template<class ValueType>
    ValueType any_cast(any& operand);
  template<class ValueType>
    ValueType any_cast(any&& operand);

  template<class ValueType>
    const ValueType* any_cast(const any* operand) noexcept;
  template<class ValueType>
    ValueType* any_cast(any* operand) noexcept;

} // namespace fundamentals_v2
} // namespace experimental
} // namespace std

6.2

Class bad_any_cast

[any.bad_any_cast]

Objects of type bad_any_cast are thrown by a failed any_cast.

6.3

Class any

[any.class]

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. [ Example: where the object constructed is holding only an int.— end example ] Such small-object optimization shall only be applied to types T for whichis_nothrow_move_constructible_v<T> is true.

6.3.1

any construct/destruct

[any.cons]

any() noexcept;

Postconditions:

this->empty().

any(const any& other);

Effects:

Constructs an object of type any with an equivalent state as other.

Throws:

Any exceptions arising from calling the selected constructor of the contained object.

any(any&& other) noexcept;

Effects:

Constructs an object of type any with a state equivalent to the original state of other.

Postconditions:

other is left in a valid but otherwise unspecified state.

template<class ValueType>
any(ValueType&& value);

Let T be equal to decay_t<ValueType>.

Requires:

T shall satisfy the CopyConstructible requirements, except for the requirements for MoveConstructible. If is_copy_constructible_v<T> is false, the program is ill-formed.

Effects:

If is_constructible_v<T, ValueType&&> is true, constructs an object of type any that contains an object of type T direct-initialized with std::forward<ValueType>(value). Otherwise, constructs an object of type any that contains an object of type T direct-initialized with value.

Remarks:

This constructor shall not participate in overload resolution if decay_t<ValueType> is the same type as any.

Throws:

Any exception thrown by the selected constructor of T.

~any();

Effects:

clear().

6.3.2

any assignments

[any.assign]

any& operator=(const any& rhs);

Effects:

any(rhs).swap(*this). No effects if an exception is thrown.

Returns:

*this.

Throws:

Any exceptions arising from the copy constructor of the contained object.

any& operator=(any&& rhs) noexcept;

Effects:

any(std::move(rhs)).swap(*this).

Returns:

*this.

Postconditions:

The state of *this is equivalent to the original state of rhs and rhs is left in a valid but otherwise unspecified state.

template<class ValueType>
any& operator=(ValueType&& rhs);

Let T be equal to decay_t<ValueType>.

Requires:

T shall satisfy the CopyConstructible requirements. If is_copy_constructible_v<T> is false, the program is ill-formed.

Effects:

Constructs an object tmp of type any that contains an object of type T direct-initialized with std::forward<ValueType>(rhs), and tmp.swap(*this). No effects if an exception is thrown.

Returns:

*this.

Remarks:

This operator shall not participate in overload resolution if decay_t<ValueType> is the same type as any.

Throws:

Any exception thrown by the selected constructor of T.

6.3.3

any modifiers

[any.modifiers]

void clear() noexcept;

Effects:

If not empty, destroys the contained object.

Postconditions:

empty() == true.

void swap(any& rhs) noexcept;

Effects:

Exchange the states of *this and rhs.

6.3.4

any observers

[any.observers]

bool empty() const noexcept;

Returns:

true if *this has no contained object, otherwise false.

const type_info& type() const noexcept;

Returns:

If *this has a contained object of type T, typeid(T); otherwise typeid(void).

[ Note: Useful for querying against types known either at compile time or only at runtime.— end note ]

6.4

Non-member functions

[any.nonmembers]

void swap(any& x, any& y) noexcept;

Effects:

x.swap(y).

template<class ValueType>
ValueType any_cast(const any& operand);template<class ValueType>
ValueType any_cast(any& operand);template<class ValueType>
ValueType any_cast(any&& operand);

Requires:

is_reference_v<ValueType> is true or is_copy_constructible_v<ValueType> is true. Otherwise the program is ill-formed.

Returns:

For the first form, *any_cast<add_const_t<remove_reference_t<ValueType>>>(&operand). For the second form, *any_cast<remove_reference_t<ValueType>>(&operand). For the third form, if is_move_constructible_v<ValueType> is true and is_lvalue_reference_v<ValueType> is false, std::move(*any_cast<remove_reference_t<ValueType>>(&operand)), otherwise, *any_cast<remove_reference_t<ValueType>>(&operand).

Throws:

bad_any_cast if operand.type() != typeid(remove_reference_t<ValueType>).

[ Example:

any x(5);                                   // x holds int
assert(any_cast<int>(x) == 5);              // cast to value
any_cast<int&>(x) = 10;                     // cast to reference
assert(any_cast<int>(x) == 10);

x = "Meow";                                 // x holds const char*
assert(strcmp(any_cast<const char*>(x), "Meow") == 0);
any_cast<const char*&>(x) = "Harry";
assert(strcmp(any_cast<const char*>(x), "Harry") == 0);

x = string("Meow");                         // x holds string
string s, s2("Jane");
s = move(any_cast<string&>(x));             // move from any
assert(s == "Meow");
any_cast<string&>(x) = move(s2);            // move to any
assert(any_cast<const string&>(x) == "Jane");

string cat("Meow");
const any y(cat);                           // const y holds string
assert(any_cast<const string&>(y) == cat);

any_cast<string&>(y);                       // error; cannot
                                            //  any_cast away const

end example ]

template<class ValueType>
const ValueType* any_cast(const any* operand) noexcept;template<class ValueType>
ValueType* any_cast(any* operand) noexcept;

Returns:

If operand != nullptr && operand->type() == typeid(ValueType), a pointer to the object contained by operand, otherwise nullptr.

[ Example:

bool is_string(const any& operand) {
  return any_cast<string>(&operand) != nullptr;
}

end example ]

7

string_view

[string.view]

The class template basic_string_view describes an object that can refer to a constant contiguous sequence of char-like (C++14 §21.1) objects with the first element of the sequence at position zero. In the rest of this section, the type of the char-like objects held in a basic_string_view object is designated by charT.

[ Note: The library provides implicit conversions from const charT* and std::basic_string<charT, ...> to std::basic_string_view<charT, ...> so that user code can accept just std::basic_string_view<charT> 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.

7.1

Header <experimental/string_view> synopsis

[string.view.synop]

namespace std {
  namespace experimental {
  inline namespace fundamentals_v2 {

    // 7.2, Class template basic_string_view
    template<class charT, class traits = char_traits<charT>>
        class basic_string_view;

    // 7.9, basic_string_view non-member comparison functions
    template<class charT, class traits>
    constexpr bool operator==(basic_string_view<charT, traits> x,
                              basic_string_view<charT, traits> y) noexcept;
    template<class charT, class traits>
    constexpr bool operator!=(basic_string_view<charT, traits> x,
                              basic_string_view<charT, traits> y) noexcept;
    template<class charT, class traits>
    constexpr bool operator< (basic_string_view<charT, traits> x,
                                 basic_string_view<charT, traits> y) noexcept;
    template<class charT, class traits>
    constexpr bool operator> (basic_string_view<charT, traits> x,
                              basic_string_view<charT, traits> y) noexcept;
    template<class charT, class traits>
    constexpr bool operator<=(basic_string_view<charT, traits> x,
                                 basic_string_view<charT, traits> y) noexcept;
    template<class charT, class traits>
    constexpr bool operator>=(basic_string_view<charT, traits> x,
                              basic_string_view<charT, traits> y) noexcept;
    // see below, sufficient additional overloads of comparison functions

    // 7.10, Inserters and extractors
    template<class charT, class traits>
      basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os,
                   basic_string_view<charT, traits> str);

    // basic_string_view typedef names
    typedef basic_string_view<char> string_view;
    typedef basic_string_view<char16_t> u16string_view;
    typedef basic_string_view<char32_t> u32string_view;
    typedef basic_string_view<wchar_t> wstring_view;

  }  // namespace fundamentals_v2
  }  // namespace experimental

  // 7.11, Hash support
  template <class T> struct hash;
  template <> struct hash<experimental::string_view>;
  template <> struct hash<experimental::u16string_view>;
  template <> struct hash<experimental::u32string_view>;
  template <> struct hash<experimental::wstring_view>;

}  // namespace std

The function templates defined in C++14 §20.2.2 and C++14 §24.7 are available when <experimental/string_view> is included.

7.2

Class template basic_string_view

[string.view.template]

template<class charT, class traits = char_traits<charT>>
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_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<class Allocator>
  basic_string_view(const basic_string<charT, traits, Allocator>& 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<class Allocator>
  explicit operator basic_string<charT, traits, Allocator>() const;
  template<class Allocator = allocator<charT> >
  basic_string<charT, traits, Allocator> 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<charT, traits>, the type traits shall satisfy the character traits requirements (C++14 §21.2), and the type traits::char_type shall name the same type as charT.

7.3

basic_string_view constructors and assignment operators

[string.view.cons]

constexpr basic_string_view() noexcept;

Effects:

Constructs an empty basic_string_view.

Postconditions:

size_ == 0 and data_ == nullptr.

template<class Allocator>
basic_string_view(const basic_string<charT, traits, Allocator>& str) noexcept;

Effects:

Constructs a basic_string_view, with the postconditions in Table 10.

Table 10 — basic_string_view(const basic_string&) effects

Element Value
data_ str.data()
size_ str.size()
constexpr basic_string_view(const charT* str);

Requires:

[str, str + traits::length(str)) is a valid range.

Effects:

Constructs a basic_string_view, with the postconditions in Table 11.

Table 11 — basic_string_view(const charT*) effects

Element Value
data_ str
size_ traits::length(str)

Complexity:

O(traits::length(str))

constexpr basic_string_view(const charT* str, size_type len);

Requires:

[str, str + len) is a valid range.

Effects:

Constructs a basic_string_view, with the postconditions in Table 12.

Table 12 — basic_string_view(const charT*, size_type) effects

Element Value
data_ str
size_ len

7.4

basic_string_view iterator support

[string.view.iterators]

typedef 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()) invalidates pointers, iterators, and references returned from str's methods.

All requirements on container iterators (C++14 §23.2) apply to basic_string_view::const_iterator as well.

constexpr const_iterator begin() const noexcept;constexpr const_iterator cbegin() const noexcept;

Returns:

An iterator such that &*begin() == data_ if !empty(), or else an unspecified value such that [begin(), end()) is a valid range.

constexpr const_iterator end() const noexcept;constexpr const_iterator cend() const noexcept;

Returns:

begin() + size().

const_reverse_iterator rbegin() const noexcept;const_reverse_iterator crbegin() const noexcept;

Returns:

const_reverse_iterator(end()).

const_reverse_iterator rend() const noexcept;const_reverse_iterator crend() const noexcept;

Returns:

const_reverse_iterator(begin()).

7.5

basic_string_view capacity

[string.view.capacity]

constexpr size_type size() const noexcept;

Returns:

size_.

constexpr size_type length() const noexcept;

Returns:

size_.

constexpr size_type max_size() const noexcept;

Returns:

The largest possible number of char-like objects that can be referred to by a basic_string_view.

constexpr bool empty() const noexcept;

Returns:

size_ == 0.

7.6

basic_string_view element access

[string.view.access]

constexpr const_reference operator[](size_type pos) const;

Requires:

pos < size().

Returns:

data_[pos].

Throws:

Nothing.

[ Note: Unlike 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;

Throws:

out_of_range if pos >= size().

Returns:

data_[pos].

constexpr const_reference front() const;

Requires:

!empty()

Returns:

data_[0].

Throws:

Nothing.

constexpr const_reference back() const;

Requires:

!empty()

Returns:

data_[size() - 1].

Throws:

Nothing.

constexpr const_pointer data() const noexcept;

Returns:

data_.

[ Note: Unlike 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 ]

7.7

basic_string_view modifiers

[string.view.modifiers]

constexpr void remove_prefix(size_type n);

Requires:

n <= size().

Effects:

Equivalent to data_ += n; size_ -= n;

constexpr void remove_suffix(size_type n);

Requires:

n <= size().

Effects:

Equivalent to size_ -= n;

constexpr void swap(basic_string_view& s) noexcept;

Effects:

Exchanges the values of *this and s.

7.8

basic_string_view string operations

[string.view.ops]

template<class Allocator>
explicit2 operator basic_string<
    charT, traits, Allocator>() const;

Effects:

Equivalent to return basic_string<charT, traits, Allocator>(begin(), end());

Complexity:

O(size())

[ Note: Users who want to control the allocator instance should call to_string(allocator).— end note ]

template<class Allocator = allocator<charT>>
basic_string<charT, traits, Allocator> to_string(
    const Allocator& a = Allocator()) const;

Returns:

basic_string<charT, traits, Allocator>(begin(), end(), a).

Complexity:

O(size())

size_type copy(charT* s, size_type n, size_type pos = 0) const;

Let rlen be the smaller of n and size() - pos.

Throws:

out_of_range if pos > size().

Requires:

[s, s + rlen) is a valid range.

Effects:

Equivalent to std::copy_n(begin() + pos, rlen, s).

Returns:

rlen.

Complexity:

O(rlen)

constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const;

Throws:

out_of_range if pos > size().

Effects:

Determines the effective length rlen of the string to reference as the smaller of n and size() - pos.

Returns:

basic_string_view(data()+pos, rlen).

constexpr int compare(basic_string_view str) const noexcept;

Effects:

Determines the effective length 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).

Complexity:

O(rlen)

Returns:

The nonzero result if the result of the comparison is nonzero. Otherwise, returns a value as indicated in Table 13.

Table 13 — compare() results

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;

Effects:

Equivalent to 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;

Effects:

Equivalent to return substr(pos1, n1).compare(str.substr(pos2, n2));

constexpr int compare(const charT* s) const;

Effects:

Equivalent to return compare(basic_string_view(s));

constexpr int compare(size_type pos1, size_type n1, const charT* s) const;

Effects:

Equivalent to 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;

Effects:

Equivalent to return substr(pos1, n1).compare(basic_string_view(s, n2));

7.8.1

Searching basic_string_view

[string.view.find]

This section specifies the basic_string_view member functions namedfind, 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;

Effects:

Determines the lowest position xpos, if possible, such that the following conditions obtain:

Returns:

xpos if the function can determine such a value for xpos. Otherwise, returns npos.

Remarks:

Uses traits::eq().

constexpr size_type rfind(basic_string_view str, size_type pos = npos) const noexcept;

Effects:

Determines the highest position xpos, if possible, such that the following conditions obtain:

Returns:

xpos if the function can determine such a value for xpos. Otherwise, returns npos.

Remarks:

Uses traits::eq().

constexpr size_type find_first_of(basic_string_view str, size_type pos = 0) const noexcept;

Effects:

Determines the lowest position xpos, if possible, such that the following conditions obtain:

Returns:

xpos if the function can determine such a value for xpos. Otherwise, returns npos.

Remarks:

Uses traits::eq().

constexpr size_type find_last_of(basic_string_view str, size_type pos = npos) const noexcept;

Effects:

Determines the highest position xpos, if possible, such that the following conditions obtain:

Returns:

xpos if the function can determine such a value for xpos. Otherwise, returns npos.

Remarks:

Uses traits::eq().

constexpr size_type find_first_not_of(basic_string_view str, size_type pos = 0) const noexcept;

Effects:

Determines the lowest position xpos, if possible, such that the following conditions obtain:

Returns:

xpos if the function can determine such a value for xpos. Otherwise, returns npos.

Remarks:

Uses traits::eq().

constexpr size_type find_last_not_of(basic_string_view str, size_type pos = npos) const noexcept;

Effects:

Determines the highest position xpos, if possible, such that the following conditions obtain:

Returns:

xpos if the function can determine such a value for xpos. Otherwise, returns npos.

Remarks:

Uses traits::eq().

7.9

basic_string_view non-member comparison functions

[string.view.comparison]

Let S be basic_string_view<charT, traits>, 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 Table 14.

Table 14 — Additional basic_string_view comparison overloads

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)

[ Example: A sample conforming implementation for operator== would be:

template<class T> using __identity = decay_t<T>;
template<class charT, class traits>
constexpr bool operator==(
    basic_string_view<charT, traits> lhs,
    basic_string_view<charT, traits> rhs) noexcept {
  return lhs.compare(rhs) == 0;
}
template<class charT, class traits>
constexpr bool operator==(
    basic_string_view<charT, traits> lhs,
    __identity<basic_string_view<charT, traits>> rhs) noexcept {
  return lhs.compare(rhs) == 0;
}
template<class charT, class traits>
constexpr bool operator==(
    __identity<basic_string_view<charT, traits>> lhs,
    basic_string_view<charT, traits> rhs) noexcept {
  return lhs.compare(rhs) == 0;
}

end example ]

template<class charT, class traits>
  constexpr bool operator==(basic_string_view<charT, traits> lhs,
                            basic_string_view<charT, traits> rhs) noexcept;

Returns:

lhs.compare(rhs) == 0.

template<class charT, class traits>
  constexpr bool operator!=(basic_string_view<charT, traits> lhs,
                            basic_string_view<charT, traits> rhs) noexcept;

Returns:

lhs.compare(rhs) != 0.

template<class charT, class traits>
  constexpr bool operator< (basic_string_view<charT, traits> lhs,
                            basic_string_view<charT, traits> rhs) noexcept;

Returns:

lhs.compare(rhs) < 0.

template<class charT, class traits>
  constexpr bool operator> (basic_string_view<charT, traits> lhs,
                            basic_string_view<charT, traits> rhs) noexcept;

Returns:

lhs.compare(rhs) > 0.

template<class charT, class traits>
  constexpr bool operator<=(basic_string_view<charT, traits> lhs,
                            basic_string_view<charT, traits> rhs) noexcept;

Returns:

lhs.compare(rhs) <= 0.

template<class charT, class traits>
  constexpr bool operator>=(basic_string_view<charT, traits> lhs,
                            basic_string_view<charT, traits> rhs) noexcept;

Returns:

lhs.compare(rhs) >= 0.

7.10

Inserters and extractors

[string.view.io]

template<class charT, class traits>
  basic_ostream<charT, traits>&
    operator<<(basic_ostream<charT, traits>& os,
               basic_string_view<charT, traits> str);

Effects:

Equivalent to return os << str.to_string();

7.11

Hash support

[string.view.hash]

template <> struct hash<experimental::string_view>;template <> struct hash<experimental::u16string_view>;template <> struct hash<experimental::u32string_view>;template <> struct hash<experimental::wstring_view>;

The template specializations shall meet the requirements of class template hash (C++14 §20.9.12).

8

Memory

[memory]

8.2

Shared-ownership pointers

[memory.smartptr]

The specification of all declarations within this sub-clause 8.2 and its sub-clauses are the same as the corresponding declarations, as specified in C++14 §20.8.2, unless explicitly specified otherwise.

8.2.1

Class template shared_ptr

[memory.smartptr.shared]


namespace std {
namespace experimental {
inline namespace fundamentals_v2 {

  template<class T> class shared_ptr {
  public:
    typedef remove_extent_t<T> element_type;
    // 8.2.1.1, shared_ptr constructors
    constexpr shared_ptr() noexcept;
    template<class Y> explicit shared_ptr(Y* p);
    template<class Y, class D> shared_ptr(Y* p, D d);
    template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);
    template <class D> shared_ptr(nullptr_t p, D d)
    template <class D, class A> shared_ptr(nullptr_t p, D d, A a);
    template<class Y> shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept;
    shared_ptr(const shared_ptr& r) noexcept;
    template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;
    shared_ptr(shared_ptr&& r) noexcept;
    template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept;
    template<class Y> explicit shared_ptr(const weak_ptr<Y>& r);
    template<class Y> shared_ptr(auto_ptr<Y>&& r);
    template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);
    constexpr shared_ptr(nullptr_t) : shared_ptr() { }

    // 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<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;
    shared_ptr& operator=(shared_ptr&& r) noexcept;
    template<class Y> shared_ptr& operator=(shared_ptr<Y>&& r) noexcept;
    template<class Y> shared_ptr& operator=(auto_ptr<Y>&& r);
    template <class Y, class D> shared_ptr& operator=(unique_ptr<Y, D>&& r);

    // C++14 §20.8.2.2.4
    void swap(shared_ptr& r) noexcept;
    void reset() noexcept;
    template<class Y> void reset(Y* p);
    template<class Y, class D> void reset(Y* p, D d);
    template<class Y, class D, class A> void reset(Y* p, D d, A a);

    // 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<class U> bool owner_before(shared_ptr<U> const& b) const;
    template<class U> bool owner_before(weak_ptr<U> const& b) const;
  };

  // C++14 §20.8.2.2.6
  template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args);
  template<class T, class A, class... Args>
    shared_ptr<T> allocate_shared(const A& a, Args&&... args);

  // C++14 §20.8.2.2.7
  template<class T, class U>
    bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
  template<class T, class U>
    bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
  template<class T, class U>
    bool operator<(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
  template<class T, class U>
    bool operator>(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
  template<class T, class U>
    bool operator<=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
  template<class T, class U>
    bool operator>=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
  template <class T>
    bool operator==(const shared_ptr<T>& a, nullptr_t) noexcept;
  template <class T>
    bool operator==(nullptr_t, const shared_ptr<T>& b) noexcept;
  template <class T>
    bool operator!=(const shared_ptr<T>& a, nullptr_t) noexcept;
  template <class T>
    bool operator!=(nullptr_t, const shared_ptr<T>& b) noexcept;
  template <class T>
    bool operator<(const shared_ptr<T>& a, nullptr_t) noexcept;
  template <class T>
    bool operator<(nullptr_t, const shared_ptr<T>& b) noexcept;
  template <class T>
    bool operator<=(const shared_ptr<T>& a, nullptr_t) noexcept;
  template <class T>
    bool operator<=(nullptr_t, const shared_ptr<T>& b) noexcept;
  template <class T>
    bool operator>(const shared_ptr<T>& a, nullptr_t) noexcept;
  template <class T>
    bool operator>(nullptr_t, const shared_ptr<T>& b) noexcept;
  template <class T>
    bool operator>=(const shared_ptr<T>& a, nullptr_t) noexcept;
  template <class T>
    bool operator>=(nullptr_t, const shared_ptr<T>& b) noexcept;

  // C++14 §20.8.2.2.8
  template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept;

  // 8.2.1.3, shared_ptr casts
  template<class T, class U>
    shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept;
  template<class T, class U>
    shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept;
  template<class T, class U>
    shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept;
  template<class T, class U>
    shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>& r) noexcept;

  // C++14 §20.8.2.2.10
  template<class D, class T> D* get_deleter(const shared_ptr<T>& p) noexcept;

  // C++14 §20.8.2.2.11
  template<class E, class T, class Y>
    basic_ostream<E, T>& operator<< (basic_ostream<E, T>& os, const shared_ptr<Y>& p);

  // C++14 §20.8.2.4
  template<class T> class owner_less;

  // C++14 §20.8.2.5
  template<class T> class enable_shared_from_this;

  // C++14 §20.8.2.6
  template<class T>
    bool atomic_is_lock_free(const shared_ptr<T>* p);
  template<class T>
    shared_ptr<T> atomic_load(const shared_ptr<T>* p);
  template<class T>
    shared_ptr<T> atomic_load_explicit(const shared_ptr<T>* p, memory_order mo);
  template<class T>
    void atomic_store(shared_ptr<T>* p, shared_ptr<T> r);
  template<class T>
    void atomic_store_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo);
  template<class T>
    shared_ptr<T> atomic_exchange(shared_ptr<T>* p, shared_ptr<T> r);
  template<class T>
    shared_ptr<T> atomic_exchange_explicit(shared_ptr<T>* p, shared_ptr<T> r,
                                           memory_order mo);
  template<class T>
    bool atomic_compare_exchange_weak(
      shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w);
  template<class T>
    bool atomic_compare_exchange_strong(
      shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w);
  template<class T>
    bool atomic_compare_exchange_weak_explicit(
      shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w,
      memory_order success, memory_order failure);
  template<class T>
    bool atomic_compare_exchange_strong_explicit(
      shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w,
      memory_order success, memory_order failure);


} // namespace fundamentals_v2
} // namespace experimental

  // 8.2.1.4, shared_ptr hash support
  template<class T> struct hash<experimental::shared_ptr<T>>;

} // namespace std

For the purposes of subclause 8.2, a pointer type Y* is said to be compatible with a pointer type T* when either Y* is convertible to T* or Y is U[N] and T is U cv [].

8.2.1.1

shared_ptr constructors

[memory.smartptr.shared.const]

template<class Y> explicit shared_ptr(Y* p);

Requires:

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*.

Effects:

When 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. If an exception is thrown, delete p is called when T is not an array type, delete[] p otherwise.

Postconditions:

use_count() == 1 && get() == p.

Throws:

bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

template<class Y, class D> shared_ptr(Y* p, D d);template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);template <class D> shared_ptr(nullptr_t p, D d);template <class D, class A> shared_ptr(nullptr_t p, D d, A a);

Requires:

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 (C++14 §17.6.3.5). The copy constructor and destructor of 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*.

Effects:

Constructs a 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. If an exception is thrown, d(p) is called.

Postconditions:

use_count() == 1 && get() == p.

Throws:

bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

template<class Y> shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept;

Effects:

Constructs a shared_ptr instance that stores p and shares ownership with r.

Postconditions:

get() == p && use_count() == r.use_count().

[ Note: To avoid the possibility of a dangling pointer, the user of this constructor must ensure that p remains valid at least until the ownership group of r is destroyed.— end note ]

[ Note: This constructor allows creation of an empty shared_ptr instance with a non-null stored pointer.— end note ]

shared_ptr(const shared_ptr& r) noexcept;template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;

Requires:

The second constructor shall not participate in the overload resolution unless Y* is compatible with T*.

Effects:

If r is empty, constructs an empty shared_ptr object; otherwise, constructs a shared_ptr object that shares ownership with r.

Postconditions:

get() == r.get() && use_count() == r.use_count().

shared_ptr(shared_ptr&& r) noexcept;template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept;

Remarks:

The second constructor shall not participate in overload resolution unless Y* is compatible with T*.

Effects:

Move-constructs a shared_ptr instance from r.

Postconditions:

*this shall contain the old value of r. r shall be empty. r.get() == 0.

template<class Y> explicit shared_ptr(const weak_ptr<Y>& r);

Requires:

Y* shall be compatible with T*.

Effects:

Constructs a shared_ptr object that shares ownership with r and stores a copy of the pointer stored in r. If an exception is thrown, the constructor has no effect.

Postconditions:

use_count() == r.use_count().

Throws:

bad_weak_ptr when r.expired().

template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);

Remarks:

This constructor shall not participate in overload resolution unless Y* is compatible with T*.

Effects:

Equivalent to shared_ptr(r.release(), r.get_deleter()) when D is not a reference type, otherwise shared_ptr(r.release(), ref(r.get_deleter())). If an exception is thrown, the constructor has no effect.

8.2.1.2

shared_ptr observers

[memory.smartptr.shared.obs]

element_type* get() const noexcept;

Returns:

The stored pointer.

T& operator*() const noexcept;

Requires:

get() != 0.

Returns:

*get().

Remarks:

When 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;

Requires:

get() != 0.

Returns:

get().

Remarks:

When 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;

Requires:

get() != 0 && i >= 0. If T is U[N], i < N.

Returns:

get()[i].

Remarks:

When 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.

8.2.1.3

shared_ptr casts

[memory.smartptr.shared.cast]

template<class T, class U> shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept;

Requires:

The expression static_cast<T*>((U*)0) shall be well formed.

Returns:

shared_ptr<T>(r, static_cast<typename shared_ptr<T>::element_type*>(r.get())).

[ Note: The seemingly equivalent expression shared_ptr<T>(static_cast<T*>(r.get())) will eventually result in undefined behavior, attempting to delete the same object twice.— end note ]

template<class T, class U> shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept;

Requires:

The expression dynamic_cast<T*>((U*)0) shall be well formed.

Returns:

[ Note: The seemingly equivalent expression shared_ptr<T>(dynamic_cast<T*>(r.get())) will eventually result in undefined behavior, attempting to delete the same object twice.— end note ]

template<class T, class U> shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept;

Requires:

The expression const_cast<T*>((U*)0) shall be well formed.

Returns:

shared_ptr<T>(r, const_cast<typename shared_ptr<T>::element_type*>(r.get())).

[ Note: The seemingly equivalent expression shared_ptr<T>(const_cast<T*>(r.get())) will eventually result in undefined behavior, attempting to delete the same object twice.— end note ]

template<class T, class U> shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>& r) noexcept;

Requires:

The expression reinterpret_cast<T*>((U*)0) shall be well formed.

Returns:

shared_ptr<T>(r, reinterpret_cast<typename shared_ptr<T>::element_type*>(r.get())).

8.2.1.4

shared_ptr hash support

[memory.smartptr.shared.hash]

template <class T> struct hash<experimental::shared_ptr<T>>;

The template specialization shall meet the requirements of class template hash (C++14 §20.9.12). For an object p of type experimental::shared_ptr<T>, hash<experimental::shared_ptr<T>>()(p) shall evaluate to the same value as hash<typename experimental::shared_ptr<T>::element_type*>()(p.get()).

8.2.2

Class template weak_ptr

[memory.smartptr.weak]


namespace std {
namespace experimental {
inline namespace fundamentals_v2 {

  template<class T> class weak_ptr {
  public:
    typedef remove_extent_t<T> element_type;

    // 8.2.2.1, weak_ptr constructors
    constexpr weak_ptr() noexcept;
    template<class Y> weak_ptr(shared_ptr<Y> const& r) noexcept;
    weak_ptr(weak_ptr const& r) noexcept;
    template<class Y> weak_ptr(weak_ptr<Y> const& r) noexcept;
    weak_ptr(weak_ptr&& r) noexcept;
    template<class Y> weak_ptr(weak_ptr<Y>&& 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<class Y> weak_ptr& operator=(weak_ptr<Y> const& r) noexcept;
    template<class Y> weak_ptr& operator=(shared_ptr<Y> const& r) noexcept;
    weak_ptr& operator=(weak_ptr&& r) noexcept;
    template<class Y> weak_ptr& operator=(weak_ptr<Y>&& 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<T> lock() const noexcept;
    template<class U> bool owner_before(shared_ptr<U> const& b) const;
    template<class U> bool owner_before(weak_ptr<U> const& b) const;
  };

  // C++14 §20.8.2.3.6
  template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;

} // namespace fundamentals_v2
} // namespace experimental
} // namespace std

8.2.2.1

weak_ptr constructors

[memory.smartptr.weak.const]

weak_ptr(const weak_ptr& r) noexcept;template<class Y> weak_ptr(const weak_ptr<Y>& r) noexcept;template<class Y> weak_ptr(const shared_ptr<Y>& r) noexcept;

Requires:

The second and third constructors shall not participate in the overload resolution unless Y* is compatible with T*.

Effects:

If 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.

Postconditions:

use_count() == r.use_count().

8.3

Type-erased allocator

[memory.type.erased.allocator]

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* (8.5). The process by which rptr is computed from alloc depends on the type of alloc as described in Table 15:

Table 15 — Computed memory_resource for type-erased allocator

If the type of alloc is then the value of rptr is
non-existent — no alloc specified The value of experimental::pmr::get_default_resource() at the time of construction.
nullptr_t The value of experimental::pmr::get_default_resource() at the time of construction.
a pointer type convertible to pmr::memory_resource* static_castexperimental::pmr::memory\_resource\*(alloc)
pmr::polymorphic_allocator alloc.resource()
any other type meeting the Allocator requirements (C++14 §17.6.3.5) a pointer to a value of type experimental::pmr::resource_adaptor where A is the type of alloc.rptr remains valid only for the lifetime of X.
None of the above The program is ill-formed.

Additionally, class C shall meet the following requirements:

8.4

Header <experimental/memory_resource> synopsis

[memory.resource.synop]

namespace 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 Tp> class polymorphic_allocator;

  template <class T1, class T2>
  bool operator==(const polymorphic_allocator<T1>& a,
                  const polymorphic_allocator<T2>& b) noexcept;
  template <class T1, class T2>
  bool operator!=(const polymorphic_allocator<T1>& a,
                  const polymorphic_allocator<T2>& b) noexcept;

  // The name resource_adaptor_imp is for exposition only.
  template <class Allocator> class resource_adaptor_imp;

  template <class Allocator>
    using resource_adaptor = resource_adaptor_imp<
      typename allocator_traits<Allocator>::template rebind_alloc<char>>;

  // 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

8.5

Class memory_resource

[memory.resource]

8.5.1

Class memory_resource overview

[memory.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;
};

8.5.2

memory_resource public member functions

[memory.resource.public]

~memory_resource();

Effects:

Destroys this memory_resource.

void* allocate(size_t bytes, size_t alignment = max_align);

Effects:

Equivalent to return do_allocate(bytes, alignment);

void deallocate(void* p, size_t bytes, size_t alignment = max_align);

Effects:

Equivalent to do_deallocate(p, bytes, alignment);

bool is_equal(const memory_resource& other) const noexcept;

Effects:

Equivalent to return do_is_equal(other);

8.5.3

memory_resource protected virtual member functions

[memory.resource.priv]

virtual void* do_allocate(size_t bytes, size_t alignment) = 0;

Requires:

Alignment shall be a power of two.

Returns:

A derived class shall implement this function to return a pointer to allocated storage (C++14 §3.7.4.2) with a size of at least bytes. The returned storage is aligned to the specified alignment, if such alignment is supported; otherwise it is aligned to max_align.

Throws:

A derived class implementation shall throw an appropriate exception if it is unable to allocate memory with the requested size and alignment.

virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0;

Requires:

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.

Effects:

A derived class shall implement this function to dispose of allocated storage.

Throws:

Nothing.

virtual bool do_is_equal(const memory_resource& other) const noexcept = 0;

Returns:

A derived class shall implement this function to return true if memory allocated from this can be deallocated from other and vice-versa; otherwise it shall return false.[ Note: The most-derived type of other might not match the type of this. For a derived class, D, a typical implementation of this function will compute dynamic_cast<const D*>(&other) and go no further (i.e., return false) if it returns nullptr.— end note ]

8.5.4

memory_resource equality

[memory.resource.eq]

bool operator==(const memory_resource& a, const memory_resource& b) noexcept;

Returns:

&a == &b || a.is_equal(b).

bool operator!=(const memory_resource& a, const memory_resource& b) noexcept;

Returns:

!(a == b).

8.6

Class template polymorphic_allocator

[memory.polymorphic.allocator.class]

8.6.1

Class template polymorphic_allocator overview

[memory.polymorphic.allocator.overview]

A specialization of class template pmr::polymorphic_allocator conforms to the Allocator requirements (C++14 §17.6.3.5). Constructed with different memory resources, different instances of the same specialization of 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 Tp>
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 <class U>
    polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept;

  polymorphic_allocator&
    operator=(const polymorphic_allocator& rhs) = default;

  Tp* allocate(size_t n);
  void deallocate(Tp* p, size_t n);

  template <class T, class... Args>
    void construct(T* p, Args&&... args);

  // Specializations for pair using piecewise construction
  template <class T1, class T2, class... Args1, class... Args2>
    void construct(pair<T1,T2>* p, piecewise_construct_t,
                   tuple<Args1...> x, tuple<Args2...> y);
  template <class T1, class T2>
    void construct(pair<T1,T2>* p);
  template <class T1, class T2, class U, class V>
    void construct(pair<T1,T2>* p, U&& x, V&& y);
  template <class T1, class T2, class U, class V>
    void construct(pair<T1,T2>* p, const std::pair<U, V>& pr);
  template <class T1, class T2, class U, class V>
    void construct(pair<T1,T2>* p, pair<U, V>&& pr);

  template <class T>
    void destroy(T* p);

  // Return a default-constructed allocator (no allocator propagation)
  polymorphic_allocator select_on_container_copy_construction() const;

  memory_resource* resource() const;
};

8.6.2

polymorphic_allocator constructors

[memory.polymorphic.allocator.ctor]

polymorphic_allocator() noexcept;

Effects:

Sets m_resource to get_default_resource().

polymorphic_allocator(memory_resource* r);

Requires:

r is non-null.

Effects:

Sets m_resource to r.

Throws:

Nothing.

Notes:

This constructor provides an implicit conversion from memory_resource*.

template <class U>
polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept;

Effects:

Sets m_resource to other.resource().

8.6.3

polymorphic_allocator member functions

[memory.polymorphic.allocator.mem]

Tp* allocate(size_t n);

Returns:

Equivalent to return static_cast<Tp*>(m_resource->allocate(n * sizeof(Tp), alignof(Tp)));

void deallocate(Tp* p, size_t n);

Requires:

p was allocated from a memory resource, x, equal to *m_resource, using x.allocate(n * sizeof(Tp), alignof(Tp)).

Effects:

Equivalent to m_resource->deallocate(p, n * sizeof(Tp), alignof(Tp)).

Throws:

Nothing.

template <class T, class... Args>
void construct(T* p, Args&&... args);

Requires:

Uses-allocator construction of T with allocator this->resource() (see 2.1) and constructor arguments std::forward<Args>(args)... is well-formed.[ Note: uses-allocator construction is always well formed for types that do not use allocators.— end note ]

Effects:

Construct a T object at p by uses-allocator construction with allocator this->resource() (2.1) and constructor arguments std::forward<Args>(args)....

Throws:

Nothing unless the constructor for T throws.

template <class T1, class T2, class... Args1, class... Args2>
void construct(pair<T1,T2>* p, piecewise_construct_t,
               tuple<Args1...> x, tuple<Args2...> y);

Effects:

Let xprime be a tuple constructed from x according to the appropriate rule from the following list.[ _Note:_ The following description can be summarized as constructing a std::pair<T1,T2> object at p as if by separate _uses-allocator construction_ with allocator this->resource() (2.1) of p->first using the elements of x and p->second using the elements of y.— end note ]

template <class T1, class T2>
void construct(std::pair<T1,T2>* p);

Effects:

Equivalent to this->construct(p, piecewise_construct, tuple<>(), tuple<>());

template <class T1, class T2, class U, class V>
void construct(std::pair<T1,T2>* p, U&& x, V&& y);

Effects:

Equivalent to this->construct(p, piecewise_construct, forward_as_tuple(std::forward<U>(x)), forward_as_tuple(std::forward<V>(y)));

template <class T1, class T2, class U, class V>
void construct(std::pair<T1,T2>* p, const std::pair<U, V>& pr);

Effects:

Equivalent to this->construct(p, piecewise_construct, forward_as_tuple(pr.first), forward_as_tuple(pr.second));

template <class T1, class T2, class U, class V>
void construct(std::pair<T1,T2>* p, std::pair<U, V>&& pr);

Effects:

Equivalent to this->construct(p, piecewise_construct,forward_as_tuple(std::forward<U>(pr.first)),forward_as_tuple(std::forward<V>(pr.second)));

template <class T>
void destroy(T* p);

Effects:

p->~T().

polymorphic_allocator select_on_container_copy_construction() const;

Returns:

polymorphic_allocator().

memory_resource* resource() const;

Returns:

m_resource.

8.6.4

polymorphic_allocator equality

[memory.polymorphic.allocator.eq]

template <class T1, class T2>
bool operator==(const polymorphic_allocator<T1>& a,
                const polymorphic_allocator<T2>& b) noexcept;

Returns:

*a.resource() == *b.resource().

template <class T1, class T2>
bool operator!=(const polymorphic_allocator<T1>& a,
                const polymorphic_allocator<T2>& b) noexcept;

Returns:

! (a == b).

8.7

template alias resource_adaptor

[memory.resource.adaptor]

8.7.1

resource_adaptor

[memory.resource.adaptor.overview]

An instance of resource_adaptor<Allocator> is an adaptor that wraps a memory_resource interface around Allocator. In order that resource_adaptor<X<T>> and resource_adaptor<X<U>> are the same type for any allocator template X and types T and U,resource_adaptor<Allocator> 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 (C++14 §17.6.3.5), the parameter to resource_adaptor shall meet the following additional requirements:


// The name resource_adaptor_imp is for exposition only.
template <class Allocator>
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 <class Allocator>
  using resource_adaptor = typename resource_adaptor_imp<
    typename allocator_traits<Allocator>::template rebind_alloc<char>>;

8.7.2

resource_adaptor_imp constructors

[memory.resource.adaptor.ctor]

explicit resource_adaptor_imp(const Allocator& a2);

Effects:

Initializes m_alloc with a2.

explicit resource_adaptor_imp(Allocator&& a2);

Effects:

Initializes m_alloc with std::move(a2).

8.7.3

resource_adaptor_imp member functions

[memory.resource.adaptor.mem]

void* do_allocate(size_t bytes, size_t alignment);

Returns:

Allocated memory obtained by calling m_alloc.allocate. The size and alignment of the allocated memory shall meet the requirements for a class derived from memory_resource (8.5).

void do_deallocate(void* p, size_t bytes, size_t alignment);

Requires:

p was previously allocated using A.allocate, where A == m_alloc, and not subsequently deallocated.

Effects:

Returns memory to the allocator using m_alloc.deallocate().

bool do_is_equal(const memory_resource& other) const noexcept;

Let p be dynamic_cast<const resource_adaptor_imp*>(&other).

Returns:

false if p is null, otherwise the value of m_alloc == p->m_alloc.

8.8

Access to program-wide memory_resource objects

[memory.resource.global]

memory_resource* new_delete_resource() noexcept;

Returns:

A pointer to a static-duration object of a type derived from 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;

Returns:

A pointer to a static-duration object of a type derived from 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;

Effects:

If 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().

Returns:

The previous value of the default memory resource pointer.

Remarks:

Calling the 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;

Returns:

The current value of the default memory resource pointer.

8.9

Pool resource classes

[memory.resource.pool]

8.9.1

Classes synchronized_pool_resource and unsynchronized_pool_resource

[memory.resource.pool.overview]

The synchronized_pool_resource and unsynchronized_pool_resource classes (collectively, pool resource classes) are general-purpose memory resources having the following qualities:

Figure 1 —

pool resource

end example ]

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;
};

8.9.2

pool_options data members

[memory.resource.pool.options]

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.

8.9.3

pool resource constructors and destructors

[memory.resource.pool.ctor]

synchronized_pool_resource(const pool_options& opts, memory_resource* upstream);unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream);

Requires:

upstream is the address of a valid memory resource.

Effects:

Constructs a pool resource object that will obtain memory from 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.[ Note: The intention is that calls to upstream->allocate() will be substantially fewer than calls to this->allocate() in most cases.— end note ] The behavior of the pooling mechanism is tuned according to the value of the opts argument.

Throws:

Nothing unless upstream->allocate() throws. It is unspecified if or under what conditions this constructor calls upstream->allocate().

virtual ~synchronized_pool_resource();virtual ~unsynchronized_pool_resource();

Effects:

Calls this->release().

8.9.4

pool resource members

[memory.resource.pool.mem]

void release();

Effects:

Calls upstream_resource()->deallocate() as necessary to release all allocated memory.[ Note: memory is released back to upstream_resource() even if deallocate has not been called for some of the allocated blocks.— end note ]

memory_resource* upstream_resource() const;

Returns:

The value of the upstream argument provided to the constructor of this object.

pool_options options() const;

Returns:

The options that control the pooling behavior of this resource. The values in the returned struct may differ from those supplied to the pool resource constructor in that values of zero will be replaced with implementation-defined defaults and sizes may be rounded to unspecified granularity.

virtual void* do_allocate(size_t bytes, size_t alignment);

Returns:

A pointer to allocated storage (C++14 §3.7.4.2) with a size of at least bytes. The size and alignment of the allocated memory shall meet the requirements for a class derived from memory_resource (8.5).

Effects:

If the pool selected for a block of size 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().

Throws:

Nothing unless upstream_resource()->allocate() throws.

virtual void do_deallocate(void* p, size_t bytes, size_t alignment);

Effects:

Return the memory at p to the pool. It is unspecified if or under what circumstances this operation will result in a call to upstream_resource()->deallocate().

Throws:

Nothing.

virtual bool unsynchronized_pool_resource::do_is_equal(const memory_resource& other) const noexcept;

Returns:

this == dynamic_cast<const unsynchronized_pool_resource*>(&other).

virtual bool synchronized_pool_resource::do_is_equal(const memory_resource& other) const noexcept;

Returns:

this == dynamic_cast<const synchronized_pool_resource*>(&other).

8.10

Class monotonic_buffer_resource

[memory.resource.monotonic.buffer]

8.10.1

Class monotonic_buffer_resource overview

[memory.resource.monotonic.buffer.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:

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;
};

8.10.2

monotonic_buffer_resource constructor and destructor

[memory.resource.monotonic.buffer.ctor]

explicit monotonic_buffer_resource(memory_resource* upstream);monotonic_buffer_resource(size_t initial_size, memory_resource* upstream);

Requires:

upstream shall be the address of a valid memory resource.initial_size, if specified, shall be greater than zero.

Effects:

Sets 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);

Requires:

upstream shall be the address of a valid memory resource.buffer_size shall be no larger than the number of bytes in buffer.

Effects:

Sets upstream_rsrc to upstream, current_buffer to buffer, and next_buffer_size to buffer_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();

Effects:

Calls this->release().

8.10.3

monotonic_buffer_resource members

[memory.resource.monotonic.buffer.mem]

void release();

Effects:

Calls upstream_rsrc->deallocate() as necessary to release all allocated memory.

[ Note: memory is released back to upstream_rsrc even if some blocks that were allocated from this have not been deallocated from this.— end note ]

memory_resource* upstream_resource() const;

Returns:

The value of upstream_rsrc.

void* do_allocate(size_t bytes, size_t alignment);

Returns:

A pointer to allocated storage (C++14 §3.7.4.2) with a size of at least bytes. The size and alignment of the allocated memory shall meet the requirements for a class derived from memory_resource (8.5).

Effects:

If the unused space in 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.

Throws:

Nothing unless upstream_rsrc->allocate() throws.

void do_deallocate(void* p, size_t bytes, size_t alignment);

Effects:

None.

Throws:

Nothing.

Remarks:

Memory used by this resource increases monotonically until its destruction.

bool do_is_equal(const memory_resource& other) const noexcept;

Returns:

this == dynamic_cast<const monotonic_buffer_resource*>(&other).

8.11

Alias templates using polymorphic memory resources

[memory.resource.aliases]

8.12

Non-owning pointers

[memory.observer.ptr]

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.[ Note: There is no watched object when the stored pointer is nullptr.— end note ] An observer takes no responsibility or ownership of any kind for its watched object, if any; in particular, there is no inherent relationship between the lifetimes of 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.

[ Note: The uses of observer_ptr include clarity of interface specification in new code, and interoperability with pointer-based legacy code.— end note ]

8.12.1

Class template observer_ptr overview

[memory.observer.ptr.overview]

namespace std {
namespace experimental {
inline namespace fundamentals_v2 {

  template <class W> class observer_ptr {
    using pointer = add_pointer_t<W>;            // exposition-only
    using reference = add_lvalue_reference_t<W>; // exposition-only
  public:
    // publish our template parameter and variations thereof
    using element_type = W;

    // 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 <class W2> constexpr observer_ptr(observer_ptr<W2>) 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

8.12.2

observer_ptr constructors

[memory.observer.ptr.ctor]

constexpr observer_ptr() noexcept;constexpr observer_ptr(nullptr_t) noexcept;

Effects:

Constructs an observer_ptr object that has no corresponding watched object.

Postconditions:

get() == nullptr.

constexpr explicit observer_ptr(pointer other) noexcept;

Postconditions:

get() == other.

template <class W2> constexpr observer_ptr(observer_ptr<W2> other) noexcept;

Postconditions:

get() == other.get().

Remarks:

This constructor shall not participate in overload resolution unless W2* is convertible to W*.

8.12.3

observer_ptr observers

[memory.observer.ptr.obs]

constexpr pointer get() const noexcept;

Returns:

The stored pointer.

constexpr reference operator*() const;

Requires:

get() != nullptr.

Returns:

*get().

Throws:

Nothing.

constexpr pointer operator->() const noexcept;

Returns:

get().

constexpr explicit operator bool() const noexcept;

Returns:

get() != nullptr.

8.12.4

observer_ptr conversions

[memory.observer.ptr.conv]

constexpr explicit operator pointer() const noexcept;

Returns:

get().

8.12.5

observer_ptr modifiers

[memory.observer.ptr.mod]

constexpr pointer release() noexcept;

Postconditions:

get() == nullptr.

Returns:

The value get() had at the start of the call to release.

constexpr void reset(pointer p = nullptr) noexcept;

Postconditions:

get() == p.

constexpr void swap(observer_ptr& other) noexcept;

Effects:

Invokes swap on the stored pointers of *this and other.

8.12.6

observer_ptr specialized algorithms

[memory.observer.ptr.special]

template <class W>
void swap(observer_ptr<W>& p1, observer_ptr<W>& p2) noexcept;

Effects:

p1.swap(p2).

template <class W> observer_ptr<W> make_observer(W* p) noexcept;

Returns:

observer_ptr<W>{p}.

template <class W1, class W2>
bool operator==(observer_ptr<W1> p1, observer_ptr<W2> p2);

Returns:

p1.get() == p2.get().

template <class W1, class W2>
bool operator!=(observer_ptr<W1> p1, observer_ptr<W2> p2);

Returns:

not (p1 == p2).

template <class W>
bool operator==(observer_ptr<W> p, nullptr_t) noexcept;template <class W>
bool operator==(nullptr_t, observer_ptr<W> p) noexcept;

Returns:

not p.

template <class W>
bool operator!=(observer_ptr<W> p, nullptr_t) noexcept;template <class W>
bool operator!=(nullptr_t, observer_ptr<W> p) noexcept;

Returns:

(bool)p.

template <class W1, class W2>
bool operator<(observer_ptr<W1> p1, observer_ptr<W2> p2);

Returns:

less<W3>()(p1.get(), p2.get()), where W3 is the composite pointer type (C++14 §5) of W1* and W2*.

template <class W1, class W2>
bool operator>(observer_ptr<W1> p1, observer_ptr<W2> p2);

Returns:

p2 < p1.

template <class W1, class W2>
bool operator<=(observer_ptr<W1> p1, observer_ptr<W2> p2);

Returns:

not (p2 < p1).

template <class W1, class W2>
bool operator>=(observer_ptr<W1> p1, observer_ptr<W2> p2);

Returns:

not (p1 < p2).

8.12.7

observer_ptr hash support

[memory.observer.ptr.hash]

template <class T> struct hash<experimental::observer_ptr<T>>;

The template specialization shall meet the requirements of class template hash (C++14 §20.9.12). For an object p of type observer_ptr<T>,hash<observer_ptr<T>>()(p) shall evaluate to the same value as hash<T*>()(p.get()).

9

Containers

[container]

9.1

Uniform container erasure

[container.erasure]

9.1.1

Header synopsis

[container.erasure.syn]

For brevity, this section specifies the contents of 9 headers, each of which behaves as described by 1.3.

namespace std {
namespace experimental {
inline namespace fundamentals_v2 {

  // 9.1.2, Function template erase_if
  // 9.1.3, Function template erase

  // <experimental/string>
  template <class charT, class traits, class A, class Predicate>
    void erase_if(basic_string<charT, traits, A>& c, Predicate pred);
  template <class charT, class traits, class A, class U>
    void erase(basic_string<charT, traits, A>& c, const U& value);

  // <experimental/deque>
  template <class T, class A, class Predicate>
    void erase_if(deque<T, A>& c, Predicate pred);
  template <class T, class A, class U>
    void erase(deque<T, A>& c, const U& value);

  // <experimental/vector>
  template <class T, class A, class Predicate>
    void erase_if(vector<T, A>& c, Predicate pred);
  template <class T, class A, class U>
    void erase(vector<T, A>& c, const U& value);

  // <experimental/forward_list>
  template <class T, class A, class Predicate>
    void erase_if(forward_list<T, A>& c, Predicate pred);
  template <class T, class A, class U>
    void erase(forward_list<T, A>& c, const U& value);

  // <experimental/list>
  template <class T, class A, class Predicate>
    void erase_if(list<T, A>& c, Predicate pred);
  template <class T, class A, class U>
    void erase(list<T, A>& c, const U& value);

  // <experimental/map>
  template <class K, class T, class C, class A, class Predicate>
    void erase_if(map<K, T, C, A>& c, Predicate pred);
  template <class K, class T, class C, class A, class Predicate>
    void erase_if(multimap<K, T, C, A>& c, Predicate pred);

  // <experimental/set>
  template <class K, class C, class A, class Predicate>
    void erase_if(set<K, C, A>& c, Predicate pred);
  template <class K, class C, class A, class Predicate>
    void erase_if(multiset<K, C, A>& c, Predicate pred);

  // <experimental/unordered_map>
  template <class K, class T, class H, class P, class A, class Predicate>
    void erase_if(unordered_map<K, T, H, P, A>& c, Predicate pred);
  template <class K, class T, class H, class P, class A, class Predicate>
    void erase_if(unordered_multimap<K, T, H, P, A>& c, Predicate pred);

  // <experimental/unordered_set>
  template <class K, class H, class P, class A, class Predicate>
    void erase_if(unordered_set<K, H, P, A>& c, Predicate pred);
  template <class K, class H, class P, class A, class Predicate>
    void erase_if(unordered_multiset<K, H, P, A>& c, Predicate pred);

} // inline namespace fundamentals_v2
} // namespace experimental
} // namespace std

9.1.2

Function template erase_if

[container.erasure.erase_if]

template <class charT, class traits, class A, class Predicate>
void erase_if(basic_string<charT, traits, A>& c, Predicate pred);template <class T, class A, class Predicate>
void erase_if(deque<T, A>& c, Predicate pred);template <class T, class A, class Predicate>
void erase_if(vector<T, A>& c, Predicate pred);

Effects:

Equivalent to: c.erase(remove_if(c.begin(), c.end(), pred), c.end());

template <class T, class A, class Predicate>
void erase_if(forward_list<T, A>& c, Predicate pred);template <class T, class A, class Predicate>
void erase_if(list<T, A>& c, Predicate pred);

Effects:

Equivalent to: c.remove_if(pred);

template <class K, class T, class C, class A, class Predicate>
void erase_if(map<K, T, C, A>& c, Predicate pred);template <class K, class T, class C, class A, class Predicate>
void erase_if(multimap<K, T, C, A>& c, Predicate pred);template <class K, class C, class A, class Predicate>
void erase_if(set<K, C, A>& c, Predicate pred);template <class K, class C, class A, class Predicate>
void erase_if(multiset<K, C, A>& c, Predicate pred);template <class K, class T, class H, class P, class A, class Predicate>
void erase_if(unordered_map<K, T, H, P, A>& c, Predicate pred);template <class K, class T, class H, class P, class A, class Predicate>
void erase_if(unordered_multimap<K, T, H, P, A>& c, Predicate pred);template <class K, class H, class P, class A, class Predicate>
void erase_if(unordered_set<K, H, P, A>& c, Predicate pred);template <class K, class H, class P, class A, class Predicate>
void erase_if(unordered_multiset<K, H, P, A>& c, Predicate pred);

Effects:

Equivalent to:

for (auto i = c.begin(), last = c.end(); i != last; ) {
  if (pred(*i)) {
    i = c.erase(i);
  } else {
    ++i;
  }
}

9.1.3

Function template erase

[container.erasure.erase]

template <class charT, class traits, class A, class U>
void erase(basic_string<charT, traits, A>& c, const U& value);template <class T, class A, class U>
void erase(deque<T, A>& c, const U& value);template <class T, class A, class U>
void erase(vector<T, A>& c, const U& value);

Effects:

Equivalent to: c.erase(remove(c.begin(), c.end(), value), c.end());

template <class T, class A, class U>
void erase(forward_list<T, A>& c, const U& value);template <class T, class A, class U>
void erase(list<T, A>& c, const U& value);

Effects:

Equivalent to: erase_if(c, [&](auto& elem) { return elem == value; });

[ Note: Overloads of erase() for associative containers and unordered associative containers are intentionally not provided.— end note ]

9.2

Class template array

[container.array]

9.2.2

Array creation functions

[container.array.creation]

template <class D = void, class... Types>
  constexpr array<VT, sizeof...(Types)> make_array(Types&&... t);

Let Ui be decay_t<Ti> for each Ti in Types.

Remarks:

The program is ill-formed if D is void and at least one Ui is a specialization of reference_wrapper.

Returns:

array<VT, sizeof...(Types)>{ std::forward<Types>(t)... }, where VT is common_type_t<Types...> if D is void, otherwise VT is D.

[ Example:

int i = 1; int& ri = i;
auto a1 = make_array(i, ri);         // a1 is of type array<int, 2>
auto a2 = make_array(i, ri, 42L);    // a2 is of type array<long, 3>
auto a3 = make_array<long>(i, ri);   // a3 is of type array<long, 2>
auto a4 = make_array<long>();        // a4 is of type array<long, 0>
auto a5 = make_array();              // ill-formed

end example ]

template <class T, size_t N>
constexpr array<remove_cv_t<T>, N> to_array(T (&a)[N]);

Returns:

An array<remove_cv_t<T>, N> such that each element is copy-initialized with the corresponding element of a.

10

Iterators library

[iterator]

10.1

Header <experimental/iterator> synopsis

[iterator.synopsis]

#include <iterator>

namespace std {
namespace experimental {
inline namespace fundamentals_v2 {

  // 10.2, Class template ostream_joiner
  template <class DelimT, class charT = char, class traits = char_traits<charT> >
      class ostream_joiner;
  template <class charT, class traits, class DelimT>
    ostream_joiner<decay_t<DelimT>, charT, traits>
    make_ostream_joiner(basic_ostream<charT, traits>& os, DelimT&& delimiter);

} // inline namespace fundamentals_v2
} // namespace experimental
} // namespace std

10.2

Class template ostream_joiner

[iterator.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 DelimT, class charT = char, class traits = char_traits<charT> >
  class ostream_joiner {
  public:
    typedef charT char_type;
    typedef traits traits_type;
    typedef basic_ostream<charT, traits> 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<typename T>
    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

10.2.1

ostream_joiner constructor

[iterator.ostream.joiner.cons]

ostream_joiner(ostream_type& s, const DelimT& delimiter);

Effects:

Initializes out_stream with std::addressof(s),delim with delimiter, and first_element with true.

ostream_joiner(ostream_type& s, DelimT&& delimiter);

Effects:

Initializes out_stream with std::addressof(s),delim with move(delimiter), and first_element with true.

10.2.2

ostream_joiner operations

[iterator.ostream.joiner.ops]

template<typename T>
ostream_joiner& operator=(const T& value);

Effects:

if (!first_element)
  *out_stream << delim;
first_element = false;
*out_stream << value;
return *this;
ostream_joiner& operator*() noexcept;

Returns:

*this.

ostream_joiner& operator++() noexcept;ostream_joiner& operator++(int) noexcept;

Returns:

*this.

10.2.3

ostream_joiner creation function

[iterator.ostream.joiner.creation]

template <class charT, class traits, class DelimT>
ostream_joiner<decay_t<DelimT>, charT, traits>
make_ostream_joiner(basic_ostream<charT, traits>& os, DelimT&& delimiter);

Returns:

ostream_joiner<decay_t<DelimT>, charT, traits>(os, forward<DelimT>(delimiter));

11

Futures

[futures]

11.2

Class template promise

[futures.promise]

The specification of all declarations within this sub-clause 11.2 and its sub-clauses are the same as the corresponding declarations, as specified in C++14 §30.6.5, unless explicitly specified otherwise.

namespace std {
  namespace experimental {
  inline namespace fundamentals_v2 {

    template <class R>
    class promise {
    public:
      typedef erased_type allocator_type;

      promise();
      template <class Allocator>
      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<R> 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 <class R>
    void swap(promise<R>& x, promise<R>& y) noexcept;

  } // namespace fundamentals_v2
  } // namespace experimental

  template <class R, class Alloc>
  struct uses_allocator<experimental::promise<R>, 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 (8.3).

11.3

Class template packaged_task

[futures.task]

The specification of all declarations within this sub-clause 11.3 and its sub-clauses are the same as the corresponding declarations, as specified in C++14 §30.6.9, unless explicitly specified otherwise.

namespace std {
  namespace experimental {
  inline namespace fundamentals_v2 {

    template <class R, class... ArgTypes>
    class packaged_task<R(ArgTypes...)> {
    public:
      typedef erased_type allocator_type;

      packaged_task() noexcept;
      template <class F>
      explicit packaged_task(F&& f);
      template <class F, class Allocator>
      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<R> get_future();

      void operator()(ArgTypes... );
      void make_ready_at_thread_exit(ArgTypes...);

      void reset();

      pmr::memory_resource* get_memory_resource();
    };

    template <class R, class... ArgTypes>
    void swap(packaged_task<R(ArgTypes...)>&, packaged_task<R(ArgTypes...)>&) noexcept;

  } // namespace fundamentals_v2
  } // namespace experimental

  template <class R, class Alloc>
  struct uses_allocator<experimental::packaged_task<R>, 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 (8.3).

12

Algorithms library

[algorithms]

12.2

[alg.search]

template<class ForwardIterator, class Searcher>
ForwardIterator search(ForwardIterator first, ForwardIterator last,
                       const Searcher& searcher);

Effects:

Equivalent to return searcher(first, last);

Remarks:

Searcher need not meet the CopyConstructible requirements.

12.3

Sampling

[alg.random.sample]

template<class PopulationIterator, class SampleIterator, class Distance>
SampleIterator sample(PopulationIterator first, PopulationIterator last,
                      SampleIterator out, Distance n);

template<class PopulationIterator, class SampleIterator,
         class Distance, class UniformRandomNumberGenerator>
SampleIterator sample(PopulationIterator first, PopulationIterator last,
                      SampleIterator out, Distance n,
                      UniformRandomNumberGenerator&& g);

Requires:

Effects:

Copies min(last−first, n) elements (the sample) from [first, last) (the population) to out such that each possible sample has equal probability of appearance.[ Note: Algorithms that obtain such effects include selection sampling and reservoir sampling.— end note ]

Returns:

The end of the resulting sample range.

Complexity:

O(last - first).

Remarks:

12.4

Shuffle

[alg.random.shuffle]

template<class RandomAccessIterator>
  void shuffle(RandomAccessIterator first, RandomAccessIterator last);

Effects:

Permutes the elements in the range [first,last) such that each possible permutation of those elements has equal probability of appearance.

Requires:

RandomAccessIterator shall satisfy the requirements of ValueSwappable (C++14 §17.6.3.2).

Complexity:

Exactly (last - first) - 1 swaps.

Remarks:

To the extent that the implementation of this function makes use of random numbers, the per-thread engine (13.2.2.1) shall serve as the implementation's source of randomness.

13

Numerics library

[numeric]

13.1

Generalized numeric operations

[numeric.ops]

13.1.1

Header <experimental/numeric> synopsis

[numeric.ops.overview]

#include <numeric>

namespace std {
namespace experimental {
inline namespace fundamentals_v2 {

  // 13.1.2, Greatest common divisor
  template<class M, class N>
  constexpr common_type_t<M,N> gcd(M m, N n);

  // 13.1.3, Least common multiple
  template<class M, class N>
  constexpr common_type_t<M,N> lcm(M m, N n);

} // inline namespace fundamentals_v2
} // namespace experimental
} // namespace std

13.1.2

Greatest common divisor

[numeric.ops.gcd]

template<class M, class N>
constexpr common_type_t<M,N> gcd(M m, N n);

Requires:

|m| shall be representable as a value of type M and|n| shall be representable as a value of type N.[ Note: These requirements ensure, for example, that gcd(m, m) = |m| is representable as a value of type M.— end note ]

Remarks:

If either M or N is not an integer type, the program is ill-formed.

Returns:

zero when m and n are both zero. Otherwise, returns the greatest common divisor of |m| and |n|.

Throws:

Nothing.

13.1.3

Least common multiple

[numeric.ops.lcm]

template<class M, class N>
constexpr common_type_t<M,N> lcm(M m, N n);

Requires:

|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,N>.

Remarks:

If either M or N is not an integer type, the program is ill-formed.

Returns:

zero when either m or n is zero. Otherwise, returns the least common multiple of |m| and |n|.

Throws:

Nothing.

13.2

Random number generation

[rand]

13.2.1

Header <experimental/random> synopsis

[rand.synopsis]

#include <random>

namespace std {
namespace experimental {
inline namespace fundamentals_v2 {

  // 13.2.2.1, Function template randint
  template <class IntType>
  IntType randint(IntType a, IntType b);
  void reseed();
  void reseed(default_random_engine::result_type value);

} // inline namespace fundamentals_v2
} // namespace experimental
} // namespace std

13.2.2

Utilities

[rand.util]

13.2.2.1

Function template randint

[rand.util.randint]

A separate per-thread engine of type default_random_engine (C++14 §26.5.5), initialized to an unpredictable state, shall be maintained for each thread.

template<class IntType>
IntType randint(IntType a, IntType b);

Requires:

ab.

Remarks:

If the template argument does not meet the requirements for IntType (C++14 §26.5.1.1), the program is ill-formed.

Returns:

A random integer i, a ≤ i ≤ b, produced from a thread-local instance of uniform_int_distribution<IntType> (C++14 §26.5.8.2.1) invoked with the per-thread engine.

void reseed();void reseed(default_random_engine::result_type value);

Effects:

Let g be the per-thread engine. The first form sets g to an unpredictable state. The second form invokes g.seed(value).

Postconditions:

Subsequent calls to randint do not depend on values produced by g before calling reseed.[ Note: reseed also resets any instances of uniform_int_distribution used by randint.— end note ]

14

Reflection library

[reflection]

14.1

Class source_location

[reflection.src_loc]

14.1.1

Header <experimental/source_location> synopsis

[reflection.src_loc.synop]

namespace 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

[ Note: The intent of source_location is to have a small size and efficient copying.— end note ]

14.1.2

source_location creation

[reflection.src_loc.creation]

static constexpr source_location current() noexcept;

Returns:

When invoked by a function call (C++14 §5.2.2) whose postfix-expression is a (possibly parenthesized) id-expression naming current, returns a source_location with an implementation-defined value. The value should be affected by #line (C++14 §16.4) in the same manner as for __LINE__ and __FILE__. If invoked in some other way, the value returned is unspecified.

Remarks:

When a brace-or-equal-initializer is used to initialize a non-static data member, any calls to current should correspond to the location of the constructor or aggregate initialization that initializes the member.

[ Note: When used as a default argument (C++14 §8.3.6), the value of the source_location will be the location of the call to current at the call site.— end note ]

[ Example:

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;

Effects:

Constructs an object of class source_location.

Remarks:

The values are implementation-defined.

14.1.3

source_location field access

[reflection.src_loc.fields]

constexpr uint_least32_t line() const noexcept;

Returns:

The presumed line number (C++14 §16.8) represented by this object.

constexpr uint_least32_t column() const noexcept;

Returns:

An implementation-defined value representing some offset from the start of the line represented by this object.

constexpr const char* file_name() const noexcept;

Returns:

The presumed name of the current source file (C++14 §16.8) represented by this object as an NTBS.

constexpr const char* function_name() const noexcept;

Returns:

If this object represents a position in the body of a function, returns an implementation-defined NTBS that should correspond to the function name. Otherwise, returns an empty string.