A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://cplusplus.github.io/fundamentals-ts/v3.html below:

C++ Extensions for Library Fundamentals, Version 3, Working Draft

6 General utilities library[utilities] 6.1 Constness propagation[propagate_const] 6.1.1 Header <experimental/propagate_const> synopsis[propagate_const.syn]
namespace std {
  namespace experimental::inline fundamentals_v3 {

    // 6.1.2.1, Overview
    template <class T> class propagate_const;

    // 6.1.2.9, 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);

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

    // 6.1.2.11, 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;

  } // namespace experimental::inline fundamentals_v3

  // 6.1.2.12, Hash support
  template <class T> struct hash;
  template <class T>
    struct hash<experimental::fundamentals_v3::propagate_const<T>>;

  // 6.1.2.13, Comparison function objects
  template <class T> struct equal_to;
  template <class T>
    struct equal_to<experimental::fundamentals_v3::propagate_const<T>>;
  template <class T> struct not_equal_to;
  template <class T>
    struct not_equal_to<experimental::fundamentals_v3::propagate_const<T>>;
  template <class T> struct less;
  template <class T>
    struct less<experimental::fundamentals_v3::propagate_const<T>>;
  template <class T> struct greater;
  template <class T>
    struct greater<experimental::fundamentals_v3::propagate_const<T>>;
  template <class T> struct less_equal;
  template <class T>
    struct less_equal<experimental::fundamentals_v3::propagate_const<T>>;
  template <class T> struct greater_equal;
  template <class T>
    struct greater_equal<experimental::fundamentals_v3::propagate_const<T>>;

} // namespace std
6.1.2 Class template propagate_const[propagate_const.tmpl] 6.1.2.1 Overview[propagate_const.overview]
namespace std::experimental::inline fundamentals_v3 {

  template <class T> class propagate_const {
  public:
    using element_type = remove_reference_t<decltype(*declval<T&>())>;

    // 6.1.2.4, Constructors
    constexpr propagate_const() = default;
    propagate_const(const propagate_const& p) = delete;
    constexpr propagate_const(propagate_const&& p) = default;
    template <class U>
      explicit(!is_convertible_v<U, T>) constexpr propagate_const(propagate_const<U>&& pu);
    template <class U>
      explicit(!is_convertible_v<U, T>) constexpr propagate_const(U&& u);

    // 6.1.2.5, 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);

    // 6.1.2.6, 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;

    // 6.1.2.7, Non-const observers
    constexpr element_type* operator->();
    constexpr operator element_type*(); // Not always defined
    constexpr element_type& operator*();
    constexpr element_type* get();

    // 6.1.2.8, Modifiers
    constexpr void swap(propagate_const& pt) noexcept(is_nothrow_swappable<T>);

  private:
    T t_; //exposition only
  };

} // namespace std::experimental::inline fundamentals_v3

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.

6.1.2.2 General requirements on T[propagate_const.requirements]

T shall be a cv-unqualified pointer-to-object type or a cv-unqualified class type for which decltype(*declval<T&>()) is an lvalue reference to object type; otherwise the program is ill-formed.

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

6.1.2.3 Requirements on class type T[propagate_const.class_type_requirements]

If T is class type then it shall satisfy the following requirements. In this subclause t denotes an lvalue of type T, ct denotes as_const(t).

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 3 — 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 6.1.2.4 Constructors[propagate_const.ctor]
template <class U>
explicit(!is_convertible_v<U, T>) constexpr propagate_const(propagate_const<U>&& pu);
Constraints:
is_constructible_v<T, U> is true.
Effects:
Initializes t_ as if direct-non-list-initializing an object of type T with the expression std::move(pu.t_).
template <class U>
explicit(!is_convertible_v<U, T>) constexpr propagate_const(U&& u);
Constraints:
is_constructible_v<T, U> is true and decay_t<U> is not a specialization of propagate_const.
Effects:
Initializes t_ as if direct-non-list-initializing an object of type T with the expression std::forward<U>(u).
6.1.2.5 Assignment[propagate_const.assignment]
template <class U>
constexpr propagate_const& operator=(propagate_const<U>&& pu);
Constraints:
U is implicitly convertible to T.
Effects:
t_ = std::move(pu.t_).
Returns:
*this.
template <class U>
constexpr propagate_const& operator=(U&& u);
Constraints:
U is implicitly convertible to T and decay_t<U> is not a specialization of propagate_const.
Effects:
t_ = std::forward<U>(u).
Returns:
*this.
6.1.2.6 Const observers[propagate_const.const_observers]
explicit constexpr operator bool() const;
Returns:
(bool)t_.
constexpr const element_type* operator->() const;
Preconditions:
get() != nullptr.
Returns:
get().
constexpr operator const element_type*() const;
Constraints:
T is an object pointer type or has an implicit conversion to const element_type*.
Returns:
get().
constexpr const element_type& operator*() const;
Preconditions:
get() != nullptr.
Returns:
*get().
constexpr const element_type* get() const;
Returns:
t_ if T is an object pointer type, otherwise t_.get().
6.1.2.7 Non-const observers[propagate_const.non_const_observers]
constexpr element_type* operator->();
Preconditions:
get() != nullptr.
Returns:
get().
constexpr operator element_type*();
Constraints:
T is an object pointer type or has an implicit conversion to element_type*.
Returns:
get().
constexpr element_type& operator*();
Preconditions:
get() != nullptr.
Returns:
*get().
constexpr element_type* get();
Returns:
t_ if T is an object pointer type, otherwise t_.get().
6.1.2.8 Modifiers[propagate_const.modifiers]
constexpr void swap(propagate_const& pt) noexcept(is_nothrow_swappable<T>);
Preconditions:
Lvalues of type T are swappable ( C++20 §16.5.3.2 ).
Effects:
swap(t_, pt.t_).
6.1.2.9 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_.
6.1.2.10 Specialized algorithms[propagate_const.algorithms]
template <class T>
constexpr void swap(propagate_const<T>& pt1, propagate_const<T>& pt2) noexcept(see below);
Constraints:
is_swappable_v<T> is true.
Effects:
Equivalent to: pt1.swap(pt2).
Remarks:
The expression inside noexcept is equivalent to:
noexcept(pt1.swap(pt2))
6.1.2.11 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.
6.1.2.12 Hash support[propagate_const.hash]
template <class T>
struct hash<experimental::fundamentals_v3::propagate_const<T>>;

The specialization hash<experimental::fundamentals_v3::propagate_const<T>> is enabled ( C++20 §20.14.18 ) if and only if hash<T> is enabled. When enabled, for an object p of type propagate_const<T>, hash<experimental::fundamentals_v3::propagate_const<T>>()(p) evaluates to the same value as hash<T>()(p.t_).

6.1.2.13 Comparison function objects[propagate_const.comparison_function_objects]
template <class T>
struct equal_to<experimental::fundamentals_v3::propagate_const<T>>;

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

Mandates:
The specialization equal_to<T> is well-formed.
Preconditions:
The specialization equal_to<T> is well-defined.
template <class T>
struct not_equal_to<experimental::fundamentals_v3::propagate_const<T>>;

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

Mandates:
The specialization not_equal_to<T> is well-formed.
Preconditions:
The specialization not_equal_to<T> is well-defined.
template <class T>
struct less<experimental::fundamentals_v3::propagate_const<T>>;

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

Mandates:
The specialization less<T> is well-formed.
Preconditions:
The specialization less<T> is well-defined.
template <class T>
struct greater<experimental::fundamentals_v3::propagate_const<T>>;

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

Mandates:
The specialization greater<T> is well-formed.
Preconditions:
The specialization greater<T> is well-defined.
template <class T>
struct less_equal<experimental::fundamentals_v3::propagate_const<T>>;

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

Mandates:
The specialization less_equal<T> is well-formed.
Preconditions:
The specialization less_equal<T> is well-defined.
template <class T>
struct greater_equal<experimental::fundamentals_v3::propagate_const<T>>;

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

Mandates:
The specialization greater_equal<T> is well-formed.
Preconditions:
The specialization greater_equal<T> is well-defined.
6.2 Scope guard support[scopeguard] 6.2.1 Header <experimental/scope> synopsis[scope.syn]
namespace std::experimental::inline fundamentals_v3 {

  // 6.2.2, Class templates scope_exit, scope_fail, and scope_success
  template <class EF>
    class scope_exit;
  template <class EF>
    class scope_fail;
  template <class EF>
    class scope_success;

  // 6.2.3, Class template unique_resource
  template <class R, class D>
    class unique_resource;

  // 6.2.3.6, unique_resource creation
  template <class R, class D, class S=decay_t<R>>
    unique_resource<decay_t<R>, decay_t<D>>
      make_unique_resource_checked(R&& r, const S& invalid, D&& d) noexcept(see below);

} // namespace std::experimental::inline fundamentals_v3
6.2.2 Class templates scope_exit, scope_fail, and scope_success[scopeguard.exit]

The class templates scope_exit, scope_fail, and scope_success define scope guards that wrap a function object to be called on their destruction.

In this subclause, the placeholder scope-guard denotes each of these class templates. In descriptions of the class members, scope-guard refers to the enclosing class.

namespace std::experimental::inline fundamentals_v3 {

  template <class EF> class scope-guard {
  public:
    template <class EFP>
      explicit scope-guard(EFP&& f) noexcept(see below);
    scope-guard(scope-guard&& rhs) noexcept(see below);

    scope-guard(const scope-guard&) = delete;
    scope-guard& operator=(const scope-guard&) = delete;
    scope-guard& operator=(scope-guard&&) = delete;

    ~scope-guard () noexcept(see below);

    void release() noexcept;

  private:
    EF exit_function;                                 // exposition only
    bool execute_on_destruction{true};                // exposition only
    int uncaught_on_creation{uncaught_exceptions()};  // exposition only
  };

  template <class EF>
    scope-guard(EF) -> scope-guard<EF>;

}  // namespace std::experimental::inline fundamentals_v3

The class template scope_exit is a general-purpose scope guard that calls its exit function when a scope is exited. The class templates scope_fail and scope_success share the scope_exit interface, only the situation when the exit function is called differs.

[ Example:
void grow(vector<int>& v) {
  scope_success guard([]{ cout << "Good!" << endl; });
  v.resize(1024);
}
end example ]

[ Note: If the exit function object of a scope_success or scope_exit object refers to a local variable of the function where it is defined, e.g., as a lambda capturing the variable by reference, and that variable is used as a return operand in that function, it is possible for that variable to already have been returned when the scope-guard’s destructor executes, calling the exit function. This can lead to surprising behavior. end note ]

Template argument EF shall be a function object type ( C++20 §20.14 ), lvalue reference to function, or lvalue reference to function object type. If EF is an object type, it shall meet the Cpp17Destructible requirements (C++20 Table 30). Given an lvalue g of type remove_reference_t<EF>, the expression g() shall be well-formed.

The constructor parameter f in the following constructors shall be a reference to a function or a reference to a function object ( C++20 §20.14 ).

template <class EFP>
explicit scope-guard(EFP&& f) noexcept(
    is_nothrow_constructible_v<EF, EFP> ||
    is_nothrow_constructible_v<EF, EFP&>);
Constraints:
is_same_v<remove_cvref_t<EFP>, scope-guard> is false and is_constructible_v<EF, EFP> is true.
Mandates:
The expression f() is well-formed.
Preconditions:
Calling f() has well-defined behavior. For scope_exit and scope_fail, calling f() does not throw an exception.
Effects:
If EFP is not an lvalue reference type and is_nothrow_constructible_v<EF, EFP> is true, initialize exit_function with std::forward<EFP>(f); otherwise initialize exit_function with f. For scope_exit and scope_fail, if the initialization of exit_function throws an exception, calls f(). [ Note: For scope_success, f() will not be called if the initialization fails. end note ]
Throws:
Any exception thrown during the initialization of exit_function.
scope-guard(scope-guard&& rhs) noexcept(see below)
Constraints:
(is_nothrow_move_constructible_v<EF> || is_copy_constructible_v<EF>) is true.
Preconditions:
If EF is an object type:
Effects:
If is_nothrow_move_constructible_v<EF> is true, initializes exit_function with std::forward<EF>(rhs.exit_function), otherwise initializes exit_function with rhs.exit_function. Initializes execute_on_destruction from rhs.execute_on_destruction and uncaught_on_creation from rhs.uncaught_on_creation. If construction succeeds, call rhs.release(). [ Note: Copying instead of moving provides the strong exception guarantee. end note ]
Postconditions:
execute_on_destruction yields the value rhs.execute_on_destruction yielded before the construction. uncaught_on_creation yields the value rhs.uncaught_on_creation yielded before the construction.
Throws:
Any exception thrown during the initialization of exit_function.
Remarks:
The expression inside noexcept is equivalent to:
is_nothrow_move_constructible_v<EF> || is_nothrow_copy_constructible_v<EF>
~scope_exit() noexcept(true);
Effects:
Equivalent to:
if (execute_on_destruction)
  exit_function();
~scope_fail() noexcept(true);
Effects:
Equivalent to:
if (execute_on_destruction && uncaught_exceptions() > uncaught_on_creation)
  exit_function();
~scope_success() noexcept(noexcept(exit_function()));
Effects:
Equivalent to:
if (execute_on_destruction && uncaught_exceptions() <= uncaught_on_creation)
  exit_function();
[ Note: If noexcept(exit_function()) is false, exit_function() may throw an exception, notwithstanding the restrictions of C++20 §16.5.5.13 . end note ]
Throws:
Any exception thrown by exit_function().
void release() noexcept;
Effects:
Equivalent to execute_on_destruction = false.
6.2.3 Class template unique_resource[scopeguard.uniqueres] 6.2.3.1 Overview[scopeguard.uniqueres.overview]
namespace std::experimental::inline fundamentals_v3 {

  template <class R, class D> class unique_resource {
  public:
    // 6.2.3.2, Constructors
    unique_resource();
    template <class RR, class DD>
      unique_resource(RR&& r, DD&& d) noexcept(see below);
    unique_resource(unique_resource&& rhs) noexcept(see below);

    // 6.2.3.3, Destructor
    ~unique_resource();

    // 6.2.3.4, Assignment
    unique_resource& operator=(unique_resource&& rhs) noexcept(see below);

    // 6.2.3.5, Other member functions
    void reset() noexcept;
    template <class RR>
      void reset(RR&& r);
    void release() noexcept;
    const R& get() const noexcept;
    see below operator*() const noexcept;
    R operator->() const noexcept;
    const D& get_deleter() const noexcept;

  private:
    using R1 = conditional_t<is_reference_v<R>, reference_wrapper<remove_reference_t<R>>, R>;  // exposition only
    R1 resource;                  // exposition only
    D deleter;                    // exposition only
    bool execute_on_reset{true};  // exposition only
  };

  template<class R, class D>
    unique_resource(R, D) -> unique_resource<R, D>;

}  // namespace std::experimental::inline fundamentals_v3

[ Note: unique_resource is a universal RAII wrapper for resource handles. Typically, such resource handles are of trivial type and come with a factory function and a clean-up or deleter function that do not throw exceptions. The clean-up function together with the result of the creation function is used to create a unique_resource variable, that on destruction will call the clean-up function. Access to the underlying resource handle is achieved through get() and in case of a pointer type resource through a set of convenience pointer operator functions. end note ]

The template argument D shall meet the requirements of a Cpp17Destructible (C++20 Table 30) function object type ( C++20 §20.14 ), for which, given a lvalue d of type D and a lvalue r of type R, the expression d(r) shall be well-formed. D shall either meet the Cpp17CopyConstructible requirements (C++20 Table 27), or D shall meet the Cpp17MoveConstructible requirements (C++20 Table 26) and is_nothrow_move_constructible_v<D> shall be true.

For the purpose of this subclause, a resource type T is an object type that meets the requirements of Cpp17CopyConstructible (C++20 Table 27), or is an object type that meets the requirements of Cpp17MoveConstructible (C++20 Table 26) and is_nothrow_move_constructible_v<T> is true, or is an lvalue reference to a resource type. R shall be a resource type.

For the scope of the adjacent subclauses, let RESOURCE be defined as follows:

6.2.3.2 Constructors[scopeguard.uniqueres.ctor]
unique_resource()
Constraints:
is_default_constructible_v<R> && is_default_constructible_v<D> is true.
Effects:
Value-initializes resource and deleter; execute_on_reset is initialized with false.
template <class RR, class DD>
unique_resource(RR&& r, DD&& d) noexcept(see below)
Constraints:
is_constructible_v<R1, RR> &&
is_constructible_v<D , DD> &&
(is_nothrow_constructible_v<R1, RR> || is_constructible_v<R1,RR&>) &&
(is_nothrow_constructible_v<D , DD> || is_constructible_v<D ,DD&>)
is true. [ Note: The first two conditions prohibit initialization from an rvalue reference when either R1 or D is a specialization of reference_wrapper. end note ]
Mandates:
The expressions d(r), d(RESOURCE) and deleter(RESOURCE) are well-formed.
Preconditions:
Calling d(r), d(RESOURCE) or deleter(RESOURCE) has well-defined behavior and does not throw an exception.
Effects:
If is_nothrow_constructible_v<R1, RR> is true, initializes resource with std::forward<RR>(r), otherwise initializes resource with r. Then, if is_nothrow_constructible_v<D, DD> is true, initializes deleter with std::forward<DD>(d), otherwise initializes deleter with d. If initialization of resource throws an exception, calls d(r). If initialization of deleter throws an exception, calls d(RESOURCE). [ Note: The explained mechanism ensures no leaking of resources. end note ]
Throws:
Any exception thrown during initialization of resource or deleter.
Remarks:
The expression inside noexcept is equivalent to:
(is_nothrow_constructible_v<R1, RR> || is_nothrow_constructible_v<R1, RR&>) &&
(is_nothrow_constructible_v<D , DD> || is_nothrow_constructible_v<D , DD&>)
unique_resource(unique_resource&& rhs) noexcept(see below);
Effects:
First, initialize resource as follows: [ Note: If initialization of resource throws an exception, rhs is left owning the resource and will free it in due time. end note ] Then, initialize deleter as follows: If initialization of deleter throws an exception and is_nothrow_move_constructible_v<R1> is true and rhs.execute_on_reset is true:
rhs.deleter(RESOURCE);
rhs.release();
Finally, execute_on_reset is initialized with exchange(rhs.execute_on_reset, false). [ Note: The explained mechanism ensures no leaking and no double release of resources. end note ]
Remarks:
The expression inside noexcept is equivalent to:
is_nothrow_move_constructible_v<R1> && is_nothrow_move_constructible_v<D>
6.2.3.3 Destructor[scopeguard.uniqueres.dtor]
~unique_resource();
Effects:
Equivalent to reset().
6.2.3.4 Assignment[scopeguard.uniqueres.assign]
unique_resource& operator=(unique_resource&& rhs) noexcept(see below);
Preconditions:
If is_nothrow_move_assignable_v<R1> is true, R1 meets the Cpp17MoveAssignable (C++20 Table 28) requirements; otherwise R1 meets the Cpp17CopyAssignable (C++20 Table 29) requirements. If is_nothrow_move_assignable_v<D> is true, D meets the Cpp17MoveAssignable (C++20 Table 28) requirements; otherwise D meets the Cpp17CopyAssignable (C++20 Table 29) requirements.
Effects:
Equivalent to:
reset();
if constexpr (is_nothrow_move_assignable_v<R1>) {
  if constexpr (is_nothrow_move_assignable_v<D>) {
    resource = std::move(rhs.resource);
    deleter = std::move(rhs.deleter);
  } else {
    deleter = rhs.deleter;
    resource = std::move(rhs.resource);
  }
} else {
  if constexpr (is_nothrow_move_assignable_v<D>) {
    resource = rhs.resource;
    deleter = std::move(rhs.deleter);
  } else {
    resource = rhs.resource;
    deleter = rhs.deleter;
  }
}
execute_on_reset = exchange(rhs.execute_on_reset, false);
[ Note: If a copy of a member throws an exception, this mechanism leaves rhs intact and *this in the released state. end note ]
Returns:
*this.
Throws:
Any exception thrown during a copy-assignment of a member that cannot be moved without an exception.
Remarks:
The expression inside noexcept is equivalent to:
is_nothrow_move_assignable_v<R1> && is_nothrow_move_assignable_v<D>
6.2.3.5 Other member functions[scopeguard.uniqueres.members]
void reset() noexcept;
Effects:
Equivalent to:
if (execute_on_reset) {
  execute_on_reset = false;
  deleter(RESOURCE);
}
template <class RR> void reset(RR&& r);
Constraints:
the selected assignment expression statement assigning resource is well-formed.
Mandates:
The expression deleter(r) is well-formed.
Preconditions:
Calling deleter(r) has well-defined behavior and does not throw an exception.
Effects:
Equivalent to:
reset();
if constexpr (is_nothrow_assignable_v<R1&, RR>) {
  resource = std::forward<RR>(r);
} else {
  resource = as_const(r);
}
execute_on_reset = true;
If copy-assignment of resource throws an exception, calls deleter(r).
void release() noexcept;
Effects:
Equivalent to execute_on_reset = false.
const R& get() const noexcept;
Returns:
resource.
see below operator*() const noexcept;
Constraints:
is_pointer_v<R> is true and is_void_v<remove_pointer_t<R>> is false.
Effects:
Equivalent to: return *get();
Remarks:
The return type is add_lvalue_reference_t<remove_pointer_t<R>>.
R operator->() const noexcept;
Constraints:
is_pointer_v<R> is true.
Returns:
get().
const D& get_deleter() const noexcept;
Returns:
deleter.
6.2.3.6 unique_resource creation[scopeguard.uniqueres.create]
template <class R, class D, class S=decay_t<R>>
unique_resource<decay_t<R>, decay_t<D>>
  make_unique_resource_checked(R&& resource, const S& invalid, D&& d)
  noexcept(is_nothrow_constructible_v<decay_t<R>, R> &&
           is_nothrow_constructible_v<decay_t<D>, D>);
Mandates:
The expression (resource == invalid ? true : false) is well-formed.
Preconditions:
Evaluation of the expression (resource == invalid ? true : false) has well-defined behavior and does not throw an exception.
Effects:
Returns an object constructed with members initialized from std::forward<R>(resource), std::forward<D>(d), and !bool(resource == invalid). Any failure during construction of the return value will not call d(resource) if bool(resource == invalid) is true.

[ Note: This creation function exists to avoid calling a deleter function with an invalid argument. end note ]

[ Example: The following example shows its use to avoid calling fclose when fopen fails.
auto file = make_unique_resource_checked(
    ::fopen("potentially_nonexistent_file.txt", "r"),
    nullptr,
    [](auto fptr){ ::fclose(fptr); });
end example ] 6.3 Metaprogramming and type traits[meta] 6.3.1 Header <experimental/type_traits> synopsis[meta.type.syn]
#include <type_traits>

namespace std::experimental::inline fundamentals_v3 {

  // 6.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;

  // 6.3.3, Detection idiom
  struct nonesuch;

  template <template<class...> class Op, class... Args>
    using is_detected = see below;
  template <template<class...> class Op, class... Args>
    inline 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>
    inline 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>
    inline constexpr bool is_detected_convertible_v
      = is_detected_convertible<To, Op, Args...>::value;

} // namespace std::experimental::inline fundamentals_v3
6.3.2 Other type transformations[meta.trans.other]

This subclause 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++20 §20.15.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++20 §7.6.1.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()(...);
};
end example ]

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 member 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++20 §7 ), there shall be no member type. Otherwise:

The member 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 type. Otherwise:

6.3.3 Detection idiom[meta.detect]
struct nonesuch {
  ~nonesuch() = delete;
  nonesuch(nonesuch const&) = delete;
  void operator=(nonesuch const&) = delete;
};

nonesuch has no default constructor ( C++20 §11.4.4 ) or initializer-list constructor ( C++20 §9.4.4 ), and is not an aggregate ( C++20 §9.4.1 ).

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 ]

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4