C++ Logo

std-proposals

Advanced search

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

From: Egor <holyblckcat_at_[hidden]>
Date: Thu, 7 Dec 2023 21:28:21 +0600
> You may think that makes optional not play nice with templated
> conversion operators, but
> if we make the change you suggest, then someone will come in and say
> that optional doesn't
> play nice with templated conversion constructors.

In my opinion, they should use the `std::optional<T> x(std::in_place,
source);` syntax in that case (even if my suggestion is rejected).

Writing `optional<T> x(source)` when `source` is convertible to both `T`
and `optional<T>` and expecting the conversion to `T` looks quite
unintuitive to me, when the more explicit syntax with `std::in_place`
exists.

07.12.2023 20:46, Ville Voutilainen пишет:
> On Thu, 7 Dec 2023 at 07:15, Egor via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
>> Hello!
>>
>> std::optional<T> has a really greedy converting constructor. It accepts
>> almost any type that T is constructible from, and constructs a T from
>> it, even if that type is also convertible to optional<T>. Example:
>> https://gcc.godbolt.org/z/ncsYehW19
>>
>> #include <iostream>
>> #include <optional>
>> #include <source_location>
>>
>> struct A
>> {
>> template <typename T>
>> operator T()
>> {
>> std::cout <<
>> std::source_location::current().function_name() << '\n';
>> return {};
>> }
>> };
>>
>> int main()
>> {
>> std::optional<int> x(A{}); // (1) Calls `operator int`, not
>> `operator optional<int>`.
>> // std::optional<int> y = A{}; // (2) Ambiguous.
>> x = A{}; // (3) Calls `operator int`, not `operator optional<int>`.
>> }
>>
>> This is very confusing in my eyes. std::optional is first type I see in
>> the wild that doesn't play nice with templated conversion operators.
>>
>> I suggest we make this constructor of optional not participate in
>> overload resolution if the argument is convertible to optional<T>.
>>
>> This would make (2) valid, and make all three lines call A::operator
>> optional<T>.
> It was an intentional design decision to give the T in optional<T> a
> chance to convert directly
> from any U, including U=optional<Z>, if it can, instead of wrapping
> into an optional<Z> first
> and then converting T from Z.
>
> You may think that makes optional not play nice with templated
> conversion operators, but
> if we make the change you suggest, then someone will come in and say
> that optional doesn't
> play nice with templated conversion constructors.

Received on 2023-12-07 15:28:26