Skip to content

Commit

Permalink
Discuss conditional copy construction with new template trickery (#396)
Browse files Browse the repository at this point in the history
* Edits from nbx8 review
  • Loading branch information
jbcoe committed Mar 18, 2024
1 parent b494beb commit 184ca32
Showing 1 changed file with 25 additions and 10 deletions.
35 changes: 25 additions & 10 deletions DRAFT.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ should not be considered in isolation.
### Changes in R4

* Use constraints to require that the object owned by `indirect` is
copy-constructible. This ensures that `std::is_copy_constructible_v` does not
copy constructible. This ensures that `std::is_copy_constructible_v` does not
give misleading results.

* Modify comparison of `indirect` allow comparsion of valueless objects.
Expand Down Expand Up @@ -1560,27 +1560,21 @@ Both `indirect` and `polymorphic` support incomplete types. Support for an
incomplete type requires deferring the instantiation of functions with
requirements until they are used.

For example, the default constructor of `indirect` requires that `T` is default
constructible. We can't write this constraint as a requirement on `T` because
The default constructor of `indirect` requires that `T` is default
constructible. We cannot write this constraint as a requirement on `T` because
that would require `T` to be a complete type at class instantiation time.
Instead we write the constraint as a requirement on a deduced type `TT` to defer
evaluation of the constraint until the default constructor is instantiated.

```c++
template <typename TT = T>
indirect() requires std::is_default_constructible_v<TT>;
indirect() requires is_default_constructible_v<TT>;
```

We can use this technique to write constraints on the default constructor of
`indirect` and `polymorphic`. Both `indirect` and `polymorphic` are
conditionally default constructible.

The same technique cannot be used for the copy or move constructor of `indirect`
because the copy or move constructor cannot be a template. We make `indirect`
unconditionally copy and move constructible. This could be relaxed in a future
version of the C++ standard, as a non-breaking change, if it was possible to
defer the instantiation of the copy or move constructor.

The same technique cannot be used for the copy or move constructor of
`polymorphic` because that would require type information on an open set of
erased types, which is not possible: a `polymorphic` object can contain any type
Expand All @@ -1589,6 +1583,27 @@ such types are copy constructible. We make `polymorphic` unconditionally copy
and move constructible. The authors do not envisage that this could be relaxed
in a future version of the C++ standard.

While a copy constructor cannot be a template, in C++20 and later we can
conditionally constrain copy construction of `indirect` by defining:

```c++
indirect(const indirect& other) requires false = delete;

template <typename TT = T>
indirect(const indirect& other) requires is_copy_constructible_v<TT>;
```
An instantiation of the function template with `TT=T` is added to the overload
set when `indirect` is copy-constructed and will be selected if the owned object
type `T` is copy constructible. This would make copy construction conditional
for `indirect` but not for `polymorphic`. We opt for consistency and make copy
construction unconditional for both `indirect` and `polymorphic`. Making
`indirect` conditionally copy constructible in a future version of the C++
standard would require adding a template function as above and would be an ABI
break. It might be simpler to add new types for non-copyable `indirect` and
`polymorphic` objects, although we do not propose the addition of such types in
this draft.
### Implicit conversions
We decided that there should be no implicit conversion of a value `T` to an
Expand Down

0 comments on commit 184ca32

Please sign in to comment.