C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Dummy value protocol

From: Jonathan Wakely <cxx_at_[hidden]>
Date: Sat, 7 Jun 2025 19:56:45 +0100
On Sat, 7 Jun 2025, 19:44 Robin Savonen Söderholm via Std-Proposals, <
std-proposals_at_[hidden]> wrote:

> You can easily implement your own version of optional that does exactly
> that (it would even be a simpler class to implement,
>

I still wouldn't call it easy. Getting an the triviality properties of
optional correct while also being usable in constant expressions is tricky
(although easier today than it was in C++17).

And I think Avi's proposal is that his suggestion would only apply for some
specializations of optional, so for other types of would behave like
std::optional today. So it would be at least as hard as implementing
optional today, plus the new conditional features.


although not to use).
>

Wouldn't it be identical to use?


The question then is why? If you somehow think that you would gain
> performance out of it, then my suggestion is: implement this type of
> optional and show both a benchmark where it makes a significant difference
> and tell us the use case where this performance gain can be leveraged.
>
> My 2 c.
>
> P.S. you may already "pay" for a branch in the case of std::string and the
> like due to SSO, I'm sure the compiler can do something smart with the
> extra branch in optional for both move and destruction.
> D.S
>
> // Robin
>
> On Sat, Jun 7, 2025, 19:48 Avi Kivity via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> On Sat, 2025-06-07 at 19:15 +0200, Jan Schultke wrote:
>> > > Why wouldn't it work with fundamental types?
>> > > I explicitly marked them as supporting the protocol. Maybe I did a
>> > > bad job of explaining myself.
>> >
>> > Because every possible value of type int is not an empty
>> > std::optional
>> > when you put it into std::optional already. You cannot define int(-1)
>> > to be an empty std::optional after the fact, so you're stuck with
>> > effectively storing an extra bool.
>> >
>> > This behavior can obviously not be changed at this point.
>>
>>
>> But that is not my proposal. std::optional keeps its bool flag. The
>> difference is in how the special member functions are generated:
>>
>>
>> std::optional<T>::~optional() {
>> if constexpr (uses the dummy protocol) {
>> _value->~T();
>> } else {
>> if (_engaged) {
>> _value->~T();
>> }
>> }
>> }
>>
>> We avoided a conditional. For fundamental types, we didn't win
>> anything, but (say) the move constructor becomes simpler:
>>
>>
>> std::optional<T>::optional(optional&& o) {
>> // omitting exception safety
>> if constexpr (uses the dummy protocol) {
>> _engaged = std::exchange(o._engaged, false);
>> _value = std::move(o._value);
>> } else {
>> _engaged = std::exchange(o._engaged, false);
>> if (_engaged) {
>> // Can be replaced with std::relocate_at()
>> std::construct_at(&_value, std::move(o._value));
>> std::destroy_at(&o._value);
>> }
>> }
>> }
>>
>> For fundamental types, and for trivially relocatable types, moving an
>> optional becomes just data movement with no conditionals.
>>
>>
>> > On Sat, 7 Jun 2025 at 19:12, Avi Kivity <avi_at_[hidden]> wrote:
>> > >
>> > > Why wouldn't it work with fundamental types? I explicitly marked
>> > > them as supporting the protocol. Maybe I did a bad job of
>> > > explaining myself.
>> > >
>> > > And again some raises std::expected, it's not related. This is for
>> > > every container that can conditionally carry a value, std::optional
>> > > is the best example but I encountered the problem while working on
>> > > a different class (an interval type).
>> > >
>> > > On Sat, 2025-06-07 at 13:24 +0200, Jan Schultke wrote:
>> > >
>> > > I don't think it's worth the effort if it cannot work for
>> > > fundamental
>> > > types, and the ABI for std::optional is set in stone. Ideally, we
>> > > would be able to say that std::optional<X*> where nullptr stores
>> > > the
>> > > empty value, or std::optional<int> where -1 represents an empty
>> > > value,
>> > > etc.
>> > >
>> > > Those things seem feasible with std::expected with a bit of library
>> > > support. We could have something like
>> > >
>> > > std::expected<int, std::nonvalue<-1>>
>> > >
>> > >
>> > > Which would use the value "-1" to represent an unexpected object.
>> > > This
>> > > would also not break any existing code since it would use novel
>> > > types
>> > > and a novel protocol, even in the case of fundamental types.
>> > >
>> > >
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2025-06-07 18:57:04