C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Making the converting constructor of std::optional less greedy

From: Edward Catmur <ecatmur_at_[hidden]>
Date: Thu, 28 Dec 2023 16:40:20 -0600
On Wed, 27 Dec 2023 at 08:50, Edward Catmur <ecatmur_at_[hidden]> wrote:

>
>
> On Tue, 26 Dec 2023 at 22:39, Egor via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>>
>> 25.12.2023 05:19, Edward Catmur пишет:
>>
>> This won't always work. If the conversion operator is templated, it will
>>> receive the base class type, not the derived type, and the behavior for the
>>> two can be different (one of them can be rejected by SFINAE but not the
>>> other, etc).
>>>
>>
>> It seems to work; am I missing something? https://godbolt.org/z/3c5fjnqo4
>>
>> `std::is_convertible_v<const U&, secret_base<T>>` and `std::is_convertible_v<const
>> U&, optional<T>>` are not equivalent. You could have arbitrary
>> constraints on `A::operator T` that permit conversions to one and not
>> the other.
>>
> That's the trick; A can't know about `secret_base<T>` (since it's secret),
> so it can't condition conversions on that type, and any conversion that
> reaches `optional<T>` can always be extended with a derived-to-base
> conversion.
>
> If `A::operator T` constrains out `std::optional<U>` (and
> `std::in_place_t`), then the converting constructor of `std::optional<U>`
> won't accept `A`. But that is almost certainly what the user intended!
> https://godbolt.org/z/dzv68bWhG
>
>
Oops, I implemented the wrong constructor - that should be:
https://godbolt.org/z/xhjsrP4Gh

I'm reminded that https://cplusplus.github.io/LWG/issue3836 shows a similar
issue to my std::function / std::copyable_function problem - if one that is
less likely to result in a visible error. To recap, std::optional<bool> has
special handling (http://eel.is/c++draft/optional.ctor#23.4) so that
optional<bool>(optional<int>(nullopt)),
optional<bool>(optional<int>(in_place, 0)),
optional<bool>(optional<int>(in_place, 1)) have values respectively
nullopt, false, true instead of false, true, true if (as prior to LWG 3836)
the greedy converting constructor was allowed to call
optional<int>::explicit operator bool() const.

So again, we have an issue where std::optional<bool> privileges *itself*
(and its other specializations) while leaving no way for other, similar
classes to get the same benefit of avoiding unwanted converting
construction.

Received on 2023-12-28 22:40:33