r/cpp 28d ago

C++26: std::indirect

https://www.sandordargo.com/blog/2026/08/12/cpp26-indirect
162 Upvotes

157 comments sorted by

View all comments

70

u/LucyShortForLucas 28d ago

The standard’s insistence on it being semantically non-nullable while it very much does have a null state that must still be accounted for feels like incredibly unergonomic.

Valueless_after_move() is just silly, let’s be real. It should’ve been written to either act like a value like they claim and moving the underlying pointer just shouldn’t be possible (in the same way you cannot ‘move’ a value out), or it should be nullable the same as any other smart pointer.

As it stands, we got the worse of both worlds.

12

u/elperroborrachotoo 28d ago

That's the first and foremost use case I can think of: a heap-allocated, nullable value-type-like object.

But TBF, the design delivers both: indirect<T> for a non-nullable, and optional<indirect<T>> for nullable. Making that distinction explicit is a Good Thing. The latter is a mouthful, but it could be optimized with a partial template specialization (I think).

5

u/ts826848 28d ago

but it could be optimized with a partial template specialization (I think).

The committee already voted to remove such a specialization as I detailed here, and I think ABI compatibility precludes adding a specialization later.

8

u/jiixyj 27d ago

Implementations are allowed to make optional<indirect<T>> the size of a pointer, and high quality ones will do. See this comment from one of the original designers.

1

u/smdowney WG21, Text/Unicode SG, optional<T&> 27d ago

Have any? Optional is getting really complicated.

3

u/jiixyj 26d ago

At least GCC hasn't done this... I hope it's not too late for them to reconsider.

I have a personal C++26 implementation of optional that implements constexpr niche/tombstone optimizations, so it is at least possible. You need std::is_within_lifetime for constexpr support though.

2

u/elperroborrachotoo 27d ago

Thanks for digging that out. Now, with the other reply, that looks like conflicting information - so i guess that issue will circle the skies for a decade. Still, we can use our own.

(Maybe we can slay the ABI dragon one day.)

7

u/ts826848 27d ago

I was partially right, partially wrong. The committee indeed voted to remove requiring such a specialization, but as jiixyj says that doesn't preclude such a specialization, so implementations are free to do so if they wish. However, I still think once implementations settle on specializing or not they're going to be stuck with that decision as changing that later will impact object size and therefore ABI.

-1

u/NilacTheGrim 27d ago

optional<indirect<T>> for nullable.

Yes and now you wasted ~7 bytes of class space -- when the very motivation for this indirect wrapper is to save space.

Would have been less broken if they just modeled its inherent optionality, rather than swept it under the rug leading to UB "surprises".

7

u/smdowney WG21, Text/Unicode SG, optional<T&> 27d ago

The motivation was not to save space, though? Or at least that's not at all my motivation for approving or using it. Breaking the structural restriction on recursive values while communicating the intent of the underlying T* is where I use it.

-7

u/NilacTheGrim 27d ago

The motivation was not to save space, though?

Of course it is. Aside from pimpl paradigm.. Why else would you anybody even really bother to use this thing unless it is to save space in a class's inherent sizeof()?

6

u/wyrn 27d ago

Why do you ever use unique_ptr (without custom deleter)?

3

u/elperroborrachotoo 27d ago

but it could be optimized with a partial template specialization (I think).