Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discuss conditional copy construction with new template trickery #396

Merged
merged 3 commits into from
Mar 18, 2024
Merged
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
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
Loading