474 lines
17 KiB
Markdown
474 lines
17 KiB
Markdown
[smartptr.adapt]
|
||
|
||
# 20 Memory management library [[mem]](./#mem)
|
||
|
||
## 20.3 Smart pointers [[smartptr]](smartptr#adapt)
|
||
|
||
### 20.3.4 Smart pointer adaptors [smartptr.adapt]
|
||
|
||
#### [20.3.4.1](#out.ptr.t) Class template out_ptr_t [[out.ptr.t]](out.ptr.t)
|
||
|
||
[1](#out.ptr.t-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5423)
|
||
|
||
out_ptr_t is a class template used to adapt types
|
||
such as smart pointers ([[smartptr]](smartptr "20.3 Smart pointers"))
|
||
for functions that use output pointer parameters[.](#out.ptr.t-1.sentence-1)
|
||
|
||
[2](#out.ptr.t-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5428)
|
||
|
||
[*Example [1](#out.ptr.t-example-1)*:
|
||
|
||
#include <memory>#include <cstdio>int fopen_s(std::FILE** f, const char* name, const char* mode);
|
||
|
||
struct fclose_deleter {void operator()(std::FILE* f) const noexcept { std::fclose(f); }};
|
||
|
||
int main(int, char*[]) {constexpr const char* file_name = "ow.o";
|
||
std::unique_ptr<std::FILE, fclose_deleter> file_ptr; int err = fopen_s(std::out_ptr<std::FILE*>(file_ptr), file_name, "r+b"); if (err != 0)return 1; // *file_ptr is validreturn 0;}unique_ptr can be used with out_ptr to be passed into an output pointer-style function,
|
||
without needing to hold onto an intermediate pointer value and
|
||
manually delete it on error or failure[.](#out.ptr.t-2.sentence-1)
|
||
|
||
â *end example*]
|
||
|
||
[ð](#lib:out_ptr_t)
|
||
|
||
namespace std {template<class Smart, class Pointer, class... Args>class out_ptr_t {public:constexpr explicit out_ptr_t(Smart&, Args...);
|
||
out_ptr_t(const out_ptr_t&) = delete; constexpr ~out_ptr_t(); constexpr operator Pointer*() const noexcept; operator void**() const noexcept; private: Smart& s; // *exposition only* tuple<Args...> a; // *exposition only* Pointer p; // *exposition only*};}
|
||
|
||
[3](#out.ptr.t-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5480)
|
||
|
||
Pointer shall meet the [*Cpp17NullablePointer*](nullablepointer.requirements#:Cpp17NullablePointer "16.4.4.4 Cpp17NullablePointer requirements [nullablepointer.requirements]") requirements[.](#out.ptr.t-3.sentence-1)
|
||
|
||
If Smart is a specialization of shared_ptr andsizeof...(Args) == 0,
|
||
the program is ill-formed[.](#out.ptr.t-3.sentence-2)
|
||
|
||
[*Note [1](#out.ptr.t-note-1)*:
|
||
|
||
It is typically a user error to reset a shared_ptr without specifying a deleter,
|
||
as shared_ptr will replace a custom deleter upon usage of reset,
|
||
as specified in [[util.smartptr.shared.mod]](util.smartptr.shared.mod "20.3.2.2.5 Modifiers")[.](#out.ptr.t-3.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[4](#out.ptr.t-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5492)
|
||
|
||
Program-defined specializations of out_ptr_t that depend on at least one program-defined type
|
||
need not meet the requirements for the primary template[.](#out.ptr.t-4.sentence-1)
|
||
|
||
[5](#out.ptr.t-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5497)
|
||
|
||
Evaluations of the conversion functions
|
||
on the same object may conflict ([[intro.races]](intro.races "6.10.2.2 Data races"))[.](#out.ptr.t-5.sentence-1)
|
||
|
||
[ð](#lib:out_ptr_t,constructor)
|
||
|
||
`constexpr explicit out_ptr_t(Smart& smart, Args... args);
|
||
`
|
||
|
||
[6](#out.ptr.t-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5507)
|
||
|
||
*Effects*: Initializes s with smart,a with std::forward<Args>(args)..., and
|
||
value-initializes p[.](#out.ptr.t-6.sentence-1)
|
||
|
||
Then, equivalent to:
|
||
|
||
- [(6.1)](#out.ptr.t-6.1)
|
||
|
||
s.reset(); if the expression s.reset() is well-formed;
|
||
|
||
- [(6.2)](#out.ptr.t-6.2)
|
||
|
||
otherwise,s = Smart(); if is_constructible_v<Smart> is true;
|
||
|
||
- [(6.3)](#out.ptr.t-6.3)
|
||
|
||
otherwise, the program is ill-formed[.](#out.ptr.t-6.sentence-2)
|
||
|
||
[7](#out.ptr.t-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5533)
|
||
|
||
[*Note [2](#out.ptr.t-note-2)*:
|
||
|
||
The constructor is not noexcept to allow for a variety of non-terminating and safe implementation strategies[.](#out.ptr.t-7.sentence-1)
|
||
|
||
For example, an implementation can allocate
|
||
a shared_ptr's internal node in the constructor and
|
||
let implementation-defined exceptions escape safely[.](#out.ptr.t-7.sentence-2)
|
||
|
||
The destructor can then move the allocated control block in directly and
|
||
avoid any other exceptions[.](#out.ptr.t-7.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:out_ptr_t,destructor)
|
||
|
||
`constexpr ~out_ptr_t();
|
||
`
|
||
|
||
[8](#out.ptr.t-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5551)
|
||
|
||
Let SP be*POINTER_OF_OR*(Smart, Pointer) ([[memory.general]](memory.general "20.2.1 General"))[.](#out.ptr.t-8.sentence-1)
|
||
|
||
[9](#out.ptr.t-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5555)
|
||
|
||
*Effects*: Equivalent to:
|
||
|
||
- [(9.1)](#out.ptr.t-9.1)
|
||
|
||
if (p) { apply([&](auto&&... args) { s.reset(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a));} if the expressions.reset(static_cast<SP>(p), std::forward<Args>(args)...) is well-formed;
|
||
|
||
- [(9.2)](#out.ptr.t-9.2)
|
||
|
||
otherwise,if (p) { apply([&](auto&&... args) { s = Smart(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a));} if is_constructible_v<Smart, SP, Args...> is true;
|
||
|
||
- [(9.3)](#out.ptr.t-9.3)
|
||
|
||
otherwise, the program is ill-formed[.](#out.ptr.t-9.sentence-1)
|
||
|
||
[ð](#out.ptr.t-itemdecl:3)
|
||
|
||
`constexpr operator Pointer*() const noexcept;
|
||
`
|
||
|
||
[10](#out.ptr.t-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5590)
|
||
|
||
*Preconditions*: operator void**() has not been called on *this[.](#out.ptr.t-10.sentence-1)
|
||
|
||
[11](#out.ptr.t-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5594)
|
||
|
||
*Returns*: addressof(const_cast<Pointer&>(p))[.](#out.ptr.t-11.sentence-1)
|
||
|
||
[ð](#out.ptr.t-itemdecl:4)
|
||
|
||
`operator void**() const noexcept;
|
||
`
|
||
|
||
[12](#out.ptr.t-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5604)
|
||
|
||
*Constraints*: is_same_v<Pointer, void*> is false[.](#out.ptr.t-12.sentence-1)
|
||
|
||
[13](#out.ptr.t-13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5608)
|
||
|
||
*Mandates*: is_pointer_v<Pointer> is true[.](#out.ptr.t-13.sentence-1)
|
||
|
||
[14](#out.ptr.t-14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5612)
|
||
|
||
*Preconditions*: operator Pointer*() has not been called on *this[.](#out.ptr.t-14.sentence-1)
|
||
|
||
[15](#out.ptr.t-15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5616)
|
||
|
||
*Returns*: A pointer value v such that:
|
||
|
||
- [(15.1)](#out.ptr.t-15.1)
|
||
|
||
the initial value *v is equivalent to static_cast<void*>(p) and
|
||
|
||
- [(15.2)](#out.ptr.t-15.2)
|
||
|
||
any modification of *v that is not followed by a subsequent modification of *this affects the value of p during the destruction of *this,
|
||
such that static_cast<void*>(p) == *v[.](#out.ptr.t-15.sentence-1)
|
||
|
||
[16](#out.ptr.t-16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5629)
|
||
|
||
*Remarks*: Accessing *v outside the lifetime of *this has undefined behavior[.](#out.ptr.t-16.sentence-1)
|
||
|
||
[17](#out.ptr.t-17)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5634)
|
||
|
||
[*Note [3](#out.ptr.t-note-3)*:
|
||
|
||
reinterpret_cast<void**>(static_cast<Pointer*>(*this)) can be a viable implementation strategy for some implementations[.](#out.ptr.t-17.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
#### [20.3.4.2](#out.ptr) Function template out_ptr [[out.ptr]](out.ptr)
|
||
|
||
[ð](#lib:out_ptr)
|
||
|
||
`template<class Pointer = void, class Smart, class... Args>
|
||
constexpr auto out_ptr(Smart& s, Args&&... args);
|
||
`
|
||
|
||
[1](#out.ptr-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5650)
|
||
|
||
Let P be Pointer if is_void_v<Pointer> is false,
|
||
otherwise *POINTER_OF*(Smart)[.](#out.ptr-1.sentence-1)
|
||
|
||
[2](#out.ptr-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5655)
|
||
|
||
*Returns*: out_ptr_t<Smart, P, Args&&...>(s, std::forward<Args>(args)...)[.](#out.ptr-2.sentence-1)
|
||
|
||
#### [20.3.4.3](#inout.ptr.t) Class template inout_ptr_t [[inout.ptr.t]](inout.ptr.t)
|
||
|
||
[1](#inout.ptr.t-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5662)
|
||
|
||
inout_ptr_t is a class template used to adapt types
|
||
such as smart pointers ([[smartptr]](smartptr "20.3 Smart pointers"))
|
||
for functions that use output pointer parameters
|
||
whose dereferenced values may first be deleted
|
||
before being set to another allocated value[.](#inout.ptr.t-1.sentence-1)
|
||
|
||
[2](#inout.ptr.t-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5669)
|
||
|
||
[*Example [1](#inout.ptr.t-example-1)*: #include <memory>struct star_fish* star_fish_alloc();int star_fish_populate(struct star_fish** ps, const char* description);
|
||
|
||
struct star_fish_deleter {void operator() (struct star_fish* c) const noexcept;};
|
||
|
||
using star_fish_ptr = std::unique_ptr<star_fish, star_fish_deleter>;
|
||
|
||
int main(int, char*[]) { star_fish_ptr peach(star_fish_alloc()); // ...// used, need to re-makeint err = star_fish_populate(std::inout_ptr(peach), "caring clown-fish liker"); return err;}
|
||
|
||
A unique_ptr can be used with inout_ptr to be passed into an output pointer-style function[.](#inout.ptr.t-2.sentence-1)
|
||
|
||
The original value will be properly deleted
|
||
according to the function it is used with and
|
||
a new value reset in its place[.](#inout.ptr.t-2.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
[ð](#lib:inout_ptr_t)
|
||
|
||
namespace std {template<class Smart, class Pointer, class... Args>class inout_ptr_t {public:constexpr explicit inout_ptr_t(Smart&, Args...);
|
||
inout_ptr_t(const inout_ptr_t&) = delete; constexpr ~inout_ptr_t(); constexpr operator Pointer*() const noexcept; operator void**() const noexcept; private: Smart& s; // *exposition only* tuple<Args...> a; // *exposition only* Pointer p; // *exposition only*};}
|
||
|
||
[3](#inout.ptr.t-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5720)
|
||
|
||
Pointer shall meet the [*Cpp17NullablePointer*](nullablepointer.requirements#:Cpp17NullablePointer "16.4.4.4 Cpp17NullablePointer requirements [nullablepointer.requirements]") requirements[.](#inout.ptr.t-3.sentence-1)
|
||
|
||
If Smart is a specialization of shared_ptr,
|
||
the program is ill-formed[.](#inout.ptr.t-3.sentence-2)
|
||
|
||
[*Note [1](#inout.ptr.t-note-1)*:
|
||
|
||
It is impossible to properly acquire unique ownership of the managed resource
|
||
from a shared_ptr given its shared ownership model[.](#inout.ptr.t-3.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[4](#inout.ptr.t-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5729)
|
||
|
||
Program-defined specializations of inout_ptr_t that depend on at least one program-defined type
|
||
need not meet the requirements for the primary template[.](#inout.ptr.t-4.sentence-1)
|
||
|
||
[5](#inout.ptr.t-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5734)
|
||
|
||
Evaluations of the conversion functions on the same object
|
||
may conflict ([[intro.races]](intro.races "6.10.2.2 Data races"))[.](#inout.ptr.t-5.sentence-1)
|
||
|
||
[ð](#lib:inout_ptr_t,constructor)
|
||
|
||
`constexpr explicit inout_ptr_t(Smart& smart, Args... args);
|
||
`
|
||
|
||
[6](#inout.ptr.t-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5744)
|
||
|
||
*Effects*: Initializes s with smart,a with std::forward<Args>(args)..., andp to either
|
||
|
||
- [(6.1)](#inout.ptr.t-6.1)
|
||
|
||
smart if is_pointer_v<Smart> is true,
|
||
|
||
- [(6.2)](#inout.ptr.t-6.2)
|
||
|
||
otherwise, smart.get()[.](#inout.ptr.t-6.sentence-1)
|
||
|
||
[7](#inout.ptr.t-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5754)
|
||
|
||
*Remarks*: An implementation can call s.release()[.](#inout.ptr.t-7.sentence-1)
|
||
|
||
[8](#inout.ptr.t-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5758)
|
||
|
||
[*Note [2](#inout.ptr.t-note-2)*:
|
||
|
||
The constructor is not noexcept to allow for a variety of non-terminating and safe implementation strategies[.](#inout.ptr.t-8.sentence-1)
|
||
|
||
For example, an intrusive pointer implementation with a control block
|
||
can allocate in the constructor and safely fail with an exception[.](#inout.ptr.t-8.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:inout_ptr_t,destructor)
|
||
|
||
`constexpr ~inout_ptr_t();
|
||
`
|
||
|
||
[9](#inout.ptr.t-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5773)
|
||
|
||
Let SP be*POINTER_OF_OR*(Smart, Pointer) ([[memory.general]](memory.general "20.2.1 General"))[.](#inout.ptr.t-9.sentence-1)
|
||
|
||
[10](#inout.ptr.t-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5777)
|
||
|
||
Let *release-statement* be s.release(); if an implementation does not call s.release() in the constructor[.](#inout.ptr.t-10.sentence-1)
|
||
|
||
Otherwise, it is empty[.](#inout.ptr.t-10.sentence-2)
|
||
|
||
[11](#inout.ptr.t-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5782)
|
||
|
||
*Effects*: Equivalent to:
|
||
|
||
- [(11.1)](#inout.ptr.t-11.1)
|
||
|
||
apply([&](auto&&... args) { s = Smart(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a)); if is_pointer_v<Smart> is true;
|
||
|
||
- [(11.2)](#inout.ptr.t-11.2)
|
||
|
||
otherwise,*release-statement*;if (p) { apply([&](auto&&... args) { s.reset(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a));} if the expressions.reset(static_cast<SP>(p), std::forward<Args>(args)...) is well-
|
||
formed;
|
||
|
||
- [(11.3)](#inout.ptr.t-11.3)
|
||
|
||
otherwise,*release-statement*;if (p) { apply([&](auto&&... args) { s = Smart(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a));} if is_constructible_v<Smart, SP, Args...> is true;
|
||
|
||
- [(11.4)](#inout.ptr.t-11.4)
|
||
|
||
otherwise, the program is ill-formed[.](#inout.ptr.t-11.sentence-1)
|
||
|
||
[ð](#inout.ptr.t-itemdecl:3)
|
||
|
||
`constexpr operator Pointer*() const noexcept;
|
||
`
|
||
|
||
[12](#inout.ptr.t-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5826)
|
||
|
||
*Preconditions*: operator void**() has not been called on *this[.](#inout.ptr.t-12.sentence-1)
|
||
|
||
[13](#inout.ptr.t-13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5830)
|
||
|
||
*Returns*: addressof(const_cast<Pointer&>(p))[.](#inout.ptr.t-13.sentence-1)
|
||
|
||
[ð](#inout.ptr.t-itemdecl:4)
|
||
|
||
`operator void**() const noexcept;
|
||
`
|
||
|
||
[14](#inout.ptr.t-14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5840)
|
||
|
||
*Constraints*: is_same_v<Pointer, void*> is false[.](#inout.ptr.t-14.sentence-1)
|
||
|
||
[15](#inout.ptr.t-15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5844)
|
||
|
||
*Mandates*: is_pointer_v<Pointer> is true[.](#inout.ptr.t-15.sentence-1)
|
||
|
||
[16](#inout.ptr.t-16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5848)
|
||
|
||
*Preconditions*: operator Pointer*() has not been called on *this[.](#inout.ptr.t-16.sentence-1)
|
||
|
||
[17](#inout.ptr.t-17)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5852)
|
||
|
||
*Returns*: A pointer value v such that:
|
||
|
||
- [(17.1)](#inout.ptr.t-17.1)
|
||
|
||
the initial value *v is equivalent to static_cast<void*>(p) and
|
||
|
||
- [(17.2)](#inout.ptr.t-17.2)
|
||
|
||
any modification of *v that is not followed by subsequent modification of *this affects the value of p during the destruction of *this,
|
||
such that static_cast<void*>(p) == *v[.](#inout.ptr.t-17.sentence-1)
|
||
|
||
[18](#inout.ptr.t-18)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5865)
|
||
|
||
*Remarks*: Accessing *v outside the lifetime of *this has undefined behavior[.](#inout.ptr.t-18.sentence-1)
|
||
|
||
[19](#inout.ptr.t-19)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5870)
|
||
|
||
[*Note [3](#inout.ptr.t-note-3)*:
|
||
|
||
reinterpret_cast<void**>(static_cast<Pointer*>(*this)) can be a viable implementation strategy for some implementations[.](#inout.ptr.t-19.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
#### [20.3.4.4](#inout.ptr) Function template inout_ptr [[inout.ptr]](inout.ptr)
|
||
|
||
[ð](#lib:inout_ptr)
|
||
|
||
`template<class Pointer = void, class Smart, class... Args>
|
||
constexpr auto inout_ptr(Smart& s, Args&&... args);
|
||
`
|
||
|
||
[1](#inout.ptr-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5886)
|
||
|
||
Let P be Pointer if is_void_v<Pointer> is false,
|
||
otherwise *POINTER_OF*(Smart)[.](#inout.ptr-1.sentence-1)
|
||
|
||
[2](#inout.ptr-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5890)
|
||
|
||
*Returns*: inout_ptr_t<Smart, P, Args&&...>(s, std::forward<Args>(args)...)[.](#inout.ptr-2.sentence-1)
|