C++ Logo

std-proposals

Advanced search

Re: [std-proposals] std::value_or

From: <roberto.romani_at_[hidden]>
Date: Tue, 15 Nov 2022 21:51:00 +0100
Hi All

About the main concern in my proposal "value_or does too much". When I was
implementing it, I made to myself the same question. Clearly if I have sent
this proposal I arrived at the conclusion: "no", because when I start to
implement it, I realized that it is not something so complicated.
The weak_pointer is the case that I am not 100% sure, even in the definition
of the concepts it requires a special part.

@Eric your proposal of value_or is very similar to mine, just removed the
argument pack and exposing the implementation with the contained_value
overloadings, if you look my implementation
(https://github.com/roroberto/cpp_small_simple_stupid_stuff/blob/main/value_
or/value_or/value_or.h) in github you will see that I did something very
similar: all the different cases are managed using simple specialized
versions of the same function, I just kept the implementation "hidden".

To expose the implementation will have the advantage to allow to extend
value_or with other special cases, but the side effect is to expose the
implementation therefore I am not sure about it.

@Giuseppe last year I proposed a version of value_or without the support of
invocable arguments, one of the critics was "I cannot define a default
parameter that is a function that can be called, I can only pass a value". I
started to think: "is it confusing if an invocable is passed?". If I write
value_or(10, f), to work f must be or a pointer to an int or an invocable
that returns a pointer to int. A pointer to a function is not convertible to
an int, therefore it makes sense only if it is invoked. Therefore it is
clear what value_or can do if f is invocable: to invoke it.

Best Regards
Roberto




-----Original Message-----
From: Std-Proposals <std-proposals-bounces_at_[hidden]> On Behalf Of
Eric Schmidt via Std-Proposals
Sent: Tuesday 15 November 2022 08:11
To: Std-Proposals <std-proposals_at_[hidden]>
Cc: Eric Schmidt <eric41293_at_[hidden]>
Subject: Re: [std-proposals] std::value_or

On 11/14/22 6:25 PM, Giuseppe D'Angelo via Std-Proposals wrote:
> Hi,
>
> Il 13/11/22 14:27, Roberto R via Std-Proposals ha scritto:
>> In attachment you can find a draft proposal of a function
>> std::value_or, similar to std::optional::value_or.
>>
>> In previous threads I called it coalesce.
>>
>> Can you please tell me your opinion?
>>
>
> I'm very confused by the idea that one allows both "plain values" as
> well as callables that return values to check.
>
> If I call value_or with a bunch of function pointers, trying to find
> the first non-null pointer (or return the given default), is it going
> to try to *call* these pointers because they're callables?
>
> To me, the "mere" selection facility vs. try to invoke and use the
> return values ought to be spelled _very_ differently. For instance,
> for optional there's value_or (that takes a value) and the proposed
> value_or_else that takes a callable.

I agree with this, and would add that the proposed std::value_or is trying
to do too much. There are special cases for std::function, std::weak_ptr,
and std::nullptr_t.

Rather than building lots of cases into std::value_or, I think it would be
better to have a customization point that determines whether there is a
contained value, and if so what it is.

I'm thinking along the lines of

template<class T, class U>
T value_or(T&& default_value, U&& to_test) {
     decltype(auto) value = contained_value(std::forward<U&&>(to_test));
     return value ? *value : std::forward<T&&>(default_value); }

when there is a single test value.

And then we can write functions like

// Generic case
// Works for optional, pointers, unique_ptr, shared_ptr template<class T>
T&& contained_value(T&& item) {
     return std::forward<T&&>(item);
}

// Special cases

int* contained_value(nullptr_t)
{
     return nullptr;
}

template<class T>
std::optional<T> contained_value(const std::weak_ptr<T>& item) {
     auto p = item.lock();
     if (p)
         return *p;
     else
         return std::nullopt;
}

template<class T>
std::optional<T> contained_value(std::weak_ptr<T>& item) {
     return contained_value(std::as_const(item));
}

(For weak_ptr, if you don't want a copy of the T, you can pass
item.lock() to value_or.)

--
Eric Schmidt
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2022-11-15 20:51:03