C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Fwd: Extension to runtime polymorphism proposed

From: Simon Schröder <dr.simon.schroeder_at_[hidden]>
Date: Sun, 12 Apr 2026 08:59:03 +0200


On Apr 11, 2026, at 2:23 PM, Muneem via Std-Proposals <std-proposals_at_[hidden]> wrote:


On 4/10/26 20:01, Simon Schröder via Std-Proposals wrote:
>std::optional<int&> x = list[0];
Just to make sure that we are on the same page:
we both agree that "std::optional<int&> x = list[index];" 
1.  std::optional<int&> 's constructor should throw an exception if the variant returned by list[index] is not an int.
No, actually this would change the current workings of std::optional. Currently, it throws if you call value() on it. Instead, we can also check if there is a valid option and then use operator* (which is UB to use if it doesn’t contain a value). The advantage of this approach is, that you do not force anybody to use exceptions. Some people really don’t like them. There is also no harm in constructing an empty optional when it is never used.
2. For std::variant<T&...> to work, we need support from the implementation just like the support I needed for type_set<T...>, this support would be import such that we can avoid the T& to be changed, and since unions cant have references, the implementation would need to come up with some internal implementation.
Usually, if the template parameter is a T& we would implement it as a pointer internally (just like you did). To the compiler references and pointers look the same anyway (it’s just that you cannot reassign a reference to point to anything else). I think that this point is mostly solved already. As I said, I’m not sure about the status of the proposal for std::optional<T&>. But, exactly the same discussions would apply to std::variant<T&…>.

Note: the branching that I talked about for "std::variant<T&...> specialization to to some std::optional<T&> at runtime" in my email to Mr.David Brown is the checking in point one.
There is no branching needed. There is always two ways to specify conversion: one would be to write an std::variant::operator=. However, we would need to specify the desired type of the optional as a template parameter. The easier solution would be:
template <Args&…>
std::optional<T&>::optional(std::variant<Args…> &variant)
    : m_storage(std::holds_alternative<T&>(variant) ? std::get<T&>(variant) : std::nullopt)
{}

A full proposal for this extension needs to discuss/consider a few things:
1. What kind of overloads do we need (const/non-const, &/&&)
2. Additional modifiers like constexpr and noexcept
3. Do we only propose this conversion just for std::optional<T&> or also for std::optional<T>
4. What should happen if there are duplicate types inside the variant (never happens with your use case)
5. Note that this does not compile if the type T& of the optional is not one of the types of the variant

For proposing std::variant<Ts&…> we should also discuss if a std::variant should only be allowed to be either specified on only Ts… or Ts&…, or if we allow a mixture of Ts and T-refs. (Certainly, for what you want just Ts&… would suffice.) I’m not sure what the use case for a mixture would be, but I also don’t see the point in artificially restricting them.

Concerning the immutability of the selected type of a variant this is just handled by making the variable of type std::variant const. There is no std::variant::operator=() const, so we cannot reassign to a const std::variant. Unfortunately, right now we also cannot reassign a value of the proper type to a const std::variant (that’s just a syntactical/optical deficiency).

One more thing for std::variant: I want to be able to convert a std::variant<int&,float&> to a std::variant<int,float> and also to an std::optional<int>. This way the user of the type can choose between getting a reference into the tuple or a copy of the value. (We need to discuss if it makes sense to move values outside the tuple; this would be a trap for UB.)

Extending std::tuple with operator[] also needs one discussion: Do we only allow this if all the types inside the tuple are distinct? I don’t see it necessary for proposing this extension. However, I’d want for the implementation of operator[] to make the types of the std::variant returned to be distinct even if the types of std::tuple are not.

On 4/10/26 20:01, Bjorne Reese via Std-Proposals wrote:
>> 2. Add operator[] to std::tuple which returns const std::variant<Ts&…>

>Better yet, a free function that works with any tuple-like object.

1. I can agree that it will be convenient, but I would also love to emphasize that there should be a specific member function for the specific tuple<T&...> meant for runtime that has its own different implementation.

@Bjorne: I do understand what you are saying here and why. I’m personally a little annoyed by the syntax of std::get. In general, I prefer the member access syntax (and we didn’t get automatic lookup of free-standing functions for this so far). Especially with the use of runtime indices it would be more consistent with arrays, vectors, etc. when using operator[] (and I like it better). Certainly, it looks like a proposal to extend std::tuple needs to discuss operator[] vs a free-standing function. We could also mix it and get both by having operator[] call the free-standing implementation.

On Sat, Apr 11, 2026 at 10:21 AM Muneem <itfllow123_at_[hidden]> wrote:
My response my Mr.Thiago Let's forget the bench marks for a second, and focus on the larger image of the limitations that I faced In implementing a dynamic type system. Micro dispatches may not matter on a small scale but it's like if if statements get slower then the effect is small in small projects and large in large ones. Similiarly if you were to access variants again and again and again, then you have the effect of the 13500% slower speed increased. Again, dynamic typing is not a esoteric branch of programming, infact as people move towards building large infrusture to connect AI tools to automated scripts and to help them operate those tools, we need real time systems, and real time systems often require flexibility as they become complex. In the case of my virtual machine, it was meant to be a simple way to build compilers but ended up having a whole large file for dynamic typing. I would argue that the reason Python is used to deal with large systems operated by AI or some other system is precisely because it supports dynamic typing(cuz it's interpreted). In the case of python, it's slow and the way it does dynamic typing is rather not strict enough(duck typing behaviours) that though could be mitigated with newer type constrained features are still causing issues in existing python code bases. C++ on the other hands can support dynamic typing in way that allows for strict closed set dynamic typing only. If that happens then people would have no reason to use python over C++ in the majority of cases, except the ones where you just want to automate a small task.

On Fri, 10 Apr 2026, 8:02 pm Thiago Macieira via Std-Proposals, <std-proposals_at_[hidden]> wrote:
On Friday, 10 April 2026 04:34:24 Pacific Daylight Time Muneem via Std-
Proposals wrote:
> Why do we need to go in circles? Like std::variant is a union hence not
> STRICTLY DYNAMICALLY TYPED.

No, it isn't. That depends on the code you write. You can very well operate
only on the type it currently has, without changing.

For the purpose you've espoused -- using one of many possible list
implementations -- std::variant *works* *just* *fine*.

From the analyses of the assembly generated by the compiler in the benchmarks
you posted about a week ago, the difference is only where the "current type" is
kept. With std::variant, since it is kept inside of the variant, the code
emitted by the compiler ends up checking it every time. Quite likely, if you
had two visitors back-to-back, the compiler would fail to realise it's the
same current type and do two dispatches. That's a QoI problem and can be fixed
in the compiler.

With your external type selection, the compiler has an easier time proving the
choice did not change and thus optimise the code to make a single dispatch to
multiple visitors.

That doesn't mean we need a new type. In real-world scenarios, the cost of
extra dispatches is likely negligible -- as it was in the micro-benchmarks.
There may be some edge cases where it is meaningful, but that does not imply
the solution needs to be in the Standard Library. There are many specialised
algorithms and containers that aren't due to their limited usefulness to the
general public. Moreover, there is a cost in *adding* them: maintenance by the
implementations, teachability, readability, etc.

And more importantly, NONE of this implies we need a language change. That
should be an orthogonal discussion.

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
  Principal Engineer - Intel Data Center - Platform & Sys. Eng.
--
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 2026-04-12 06:59:20