On Wed, 27 Dec 2023 at 08:50, Edward Catmur <ecatmur@googlemail.com> wrote:


On Tue, 26 Dec 2023 at 22:39, Egor via Std-Proposals <std-proposals@lists.isocpp.org> 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.