Skip to content
This repository was archived by the owner on Sep 22, 2023. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
_deps
_build
build/
build*
.idea/
.vscode/
bazel-*
[Oo]ut/
.vs/
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ if (${CPP_INDIRECT_IS_SUBPROJECT})
pimpl.cpp
pimpl_test.cpp
indirect_value_test.cpp
optional_test.cpp
)

target_link_libraries(indirect_value_test
Expand Down
52 changes: 29 additions & 23 deletions documentation/p1950.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Title: <code>indirect_value</code>: A Free-Store-Allocated Value Type For C++
Shortname: P1950
URL: https://wg21.link/P1950
Revision: 1
Revision: 2
Audience: LEWG
Status: P
Group: WG21
Expand All @@ -20,6 +20,12 @@ Add a class template, `indirect_value`, to the C++ Standard Library to support f

# Change history

Changes in P1950r2

* Wording fixes.

*

Changes in P1950r1

* Add design discussion.
Expand Down Expand Up @@ -146,7 +152,7 @@ auto active = find_if(elements.begin(),

In C++, when anything in a class definition changes, dependent classes require recompilation. As early as 1992 the
Handle/Body idiom was suggested to break this dependency [J. Coplien]. From this pattern, the PImpl idiom was
specialised [H. Sutter]. Despite its relative maturity, using the PImpl idiom requires careful thought about copying
specialized [H. Sutter]. Despite its relative maturity, using the PImpl idiom requires careful thought about copying
and `const`-propagation.

```~cpp
Expand Down Expand Up @@ -356,7 +362,7 @@ pointer types:
<table>
<thead>
<tr>
<th>Method</th>
<th>Function</th>
<th>Description</th>
<th>Incomplete/Complete</th>
</tr>
Expand Down Expand Up @@ -517,7 +523,7 @@ Copying a non-empty `indirect_value` will copy the owned object so that the copi

Copying from an empty `indirect_value` produces another empty `indirect_value`.

Copying and disposal of the owned object can be customised by supplying a copier and deleter.
Copying and disposal of the owned object can be customized by supplying a copier and deleter.

The template parameter `T` of `indirect_value` must be a non-union class type.

Expand All @@ -528,7 +534,7 @@ The template parameter `T` of `indirect_value` may be an incomplete type.
### X.Z.2 Class template `indirect_value` synopsis [indirect_value.synopsis]

```
template <class T, class C = std::default_copy<T>, class D = typename std::copier_traits<C>::deleter_type>
template <class T, class C = default_copy<T>, class D = typename copier_traits<C>::deleter_type>
class indirect_value {
public:
using value_type = T;
Expand All @@ -540,8 +546,8 @@ The template parameter `T` of `indirect_value` may be an incomplete type.
indirect_value(const indirect_value& p);
indirect_value(indirect_value&& p) noexcept;

template <class ...Ts>
indirect_value(std::in_place_t, Ts&&... ts); // See below
template <class... Ts>
indirect_value(in_place_t, Ts&&... ts); // See below

// Destructor
~indirect_value();
Expand All @@ -562,7 +568,7 @@ The template parameter `T` of `indirect_value` may be an incomplete type.
};

// indirect_value creation
template <class T, class ...Ts> indirect_value<T>
template <class T, class... Ts> indirect_value<T>
make_indirect_value(Ts&& ...ts); // See below

// indirect_value specialized algorithms
Expand All @@ -576,15 +582,15 @@ The template parameter `T` of `indirect_value` may be an incomplete type.
### X.Z.3 Class template `indirect_value` constructors [indirect_value.ctor]

<code>constexpr indirect_value() noexcept;</code>
* Remarks: The method shall work with incomplete pointer type for `T`.
* Remarks: The function shall work with incomplete pointer type for `T`.
* Effects: Constructs an empty `indirect_value`.
* Postconditions: `bool(*this) == false`.

<code>explicit indirect_value(T* p, C c=C{}, D d=D{});</code>
* Effects: Creates an `indirect_value` object that owns the pointer `p`. If `p` is non-null then the copier and deleter of the `indirect_value` constructed are moved from `c` and `d`.
* Requires: `C` and `D` satisfy the requirements of CopyConstructible. If the arguments `c` and/or `d` are not supplied, then `C` and/or `D` respectively are default constructible types that are not pointer types. If `p` is non-null then the expression `c(*p)` returns an object of type `T*`. The expression `d(p)` is well-formed, has well-defined behaviour, and does not throw exceptions.
* Preconditions: `C` and `D` satisfy the requirements of CopyConstructible. If the arguments `c` and/or `d` are not supplied, then `C` and/or `D` respectively are default constructible types that are not pointer types. If `p` is non-null then the expression `c(*p)` returns an object of type `T*`. The expression `d(p)` is well-formed, has well-defined behaviour, and does not throw exceptions.
* Postconditions: `bool(*this) == bool(p)`.
* Remarks: A custom copier and deleter are said to be ‘present’ in a `indirect_value` initialised with this constructor.
* Remarks: A custom copier and deleter are said to be ‘present’ in a `indirect_value` initialized with this constructor.

<code>indirect_value(const indirect_value& p);</code>
* Constraints: `is_copy_constructible_v<T>`
Expand All @@ -595,12 +601,12 @@ The template parameter `T` of `indirect_value` may be an incomplete type.
<code>indirect_value(indirect_value&& p) noexcept;</code>
* Effects: Move-constructs an `indirect_value` instance from `p`. If `p` has a custom copier and deleter then the copier and deleter of the `indirect_value` constructed are the same as those in `p`.
* Postconditions: `*this` contains the old value of `p`. `p` is empty.
* Remarks: The method shall work with incomplete pointer type for `T`.
* Remarks: The function shall work with incomplete pointer type for `T`.

<code>indirect_value(std::in_place_t, Ts&& ...ts);</code>
* Effects: Constructs an `indirect_value` which owns an object of type `T` direct-non-list-initialized with `std::forward<Ts>(ts)...`
* Throws: Any exception thrown by the selected constructor of `T` or `bad_alloc` if required storage cannot be obtained.
* Requires `is_same_v<C, default_copy> && is_same_v<D, default_delete>`.
* Preconditions `is_same_v<C, default_copy> && is_same_v<D, default_delete>`.

### X.Z.4 Class template `indirect_value` destructor [indirect_value.dtor]
<code>~indirect_value();</code>
Expand All @@ -609,7 +615,7 @@ The template parameter `T` of `indirect_value` may be an incomplete type.
### X.Z.5 Class template `indirect_value` assignment [indirect_value.assignment]
<code>indirect_value& operator=(const indirect_value& p);</code>
* Constraints: `is_copy_assignable<T>`
* Effects: `*this` owns a copy of the resource managed by `p`. If `p` has a custom copier and deleter then the copy is created by the copier in `p`, and the copier and deleter of `*this` are copied from those in `p`. Otherwise, the resource managed by `*this` is initialised by the copy constructor of the resource managed by `p`.
* Effects: `*this` owns a copy of the resource managed by `p`. If `p` has a custom copier and deleter then the copy is created by the copier in `p`, and the copier and deleter of `*this` are copied from those in `p`. Otherwise, the resource managed by `*this` is initialized by the copy constructor of the resource managed by `p`.
* Throws: Any exception thrown by the copier or `bad_alloc` if required storage cannot be obtained.
* Returns: `*this`.
* Postconditions: `bool(*this) == bool(p)`.
Expand All @@ -622,42 +628,42 @@ The template parameter `T` of `indirect_value` may be an incomplete type.
### X.Z.6 Class template `indirect_value` modifiers [indirect_value.modifiers]
<code>void swap(indirect_value<T>& p) noexcept;</code>
* Effects: Exchanges the contents of `p` and `*this`.
* Remarks: The method shall work with incomplete pointer type for `T`.
* Remarks: The function shall work with incomplete pointer type for `T`.

### X.Z.7 Class template `indirect_value` observers [indirect_value.observers]
```
T& operator*();
const T& operator*() const;
```
* Requires: `bool(*this)`.
* Preconditions: `bool(*this)`.
* Returns: A reference to the owned object.

```
T* operator->() noexcept;
const T* operator->() const noexcept;
```
* Requires: `bool(*this)`.
* Preconditions: `bool(*this)`.
* Returns: A pointer to the owned object.
* Remarks: The method shall work with incomplete pointer type for `T`.
* Remarks: The function shall work with incomplete pointer type for `T`.

<code>explicit operator bool() const noexcept;</code>
* Returns: false if the `indirect_value` is empty, otherwise true.
* Remarks: The method shall work with incomplete pointer type for `T`.
* Remarks: The function shall work with incomplete pointer type for `T`.

### X.Z.8 Class template `indirect_value` creation [indirect_value.creation]

```cpp
template <class T, class U=T, class ...Ts> indirect_value<T>
template <class T, class U=T, class... Ts> indirect_value<T>
make_indirect_value(Ts&& ...ts);
```

* Constraints: `is_constructible_v<U, Ts...>` is true.
* Expects: `U` meets the `Cpp17CopyConstructible` requirements.
* Preconditions: `U` meets the `Cpp17CopyConstructible` requirements.
* Returns: A `indirect_value<T>` owning an object of type direct-non-list-initialized with `std::forward<Ts>(ts)...`.
* Requires `is_same_v<C, default_copy> && is_same_v<D, default_delete>`.
* Preconditions `is_same_v<C, default_copy> && is_same_v<D, default_delete>`.

# Acknowledgements
The authors would like to thank Thomas Russell, and Andrew Bennieston for useful discussions on the topic and the BSI panel for on-going support.
The authors would like to thank Kilian Henneberger, Ed Catmur, Malcolm Parsons & Stephen Kelly for contitibutions to the open source implmementation. Thanks to LEWG, Thomas Russell, and Andrew Bennieston for useful discussions on the topic and the BSI panel for on-going support.

# References

Expand Down
Loading