Date: Mon, 14 Nov 2022 23:11:28 -0800
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.)
> 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
Received on 2022-11-15 07:11:39