C++ Logo

std-proposals

Advanced search

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

From: Muneem <itfllow123_at_[hidden]>
Date: Wed, 8 Apr 2026 07:22:09 +0500
>What on earth is arguing for "comfortable"?? I ask for technical
reasons why you need things like this and this is not the answer.
***ANSWER***
1. The issue with heterogeneous lists is the fact that they can allow any
type, so:
Selector(runtime index).print()
A user would not use heterogeneous lists in such cases if the list can
include sensitive information. Basically adding flexibility leads to a
whole class of issues, and the fix to all of them is a expression type T^
for every T, so that the user can provide overloads for that.

>> I SAID: 3. The new T^ is important because it is what type_set(selector)
decays into, If I had said that type_set(selector) decays to a T lvalue or
a T xvlaue then that would require some modifications to them which would
break the zero overbead principle.

>Mr.Marcin asked:What modifications?
***ANSWER*** ($$$$1.1$$$$)
For type_set(selector) to decay into T^ for every T in selector, the
compiler would have a specific implementation defined constant
representation of T^ that is efficient for this one instantiaton goal. T^
is a glvalue so it stores the information, but the layout of that
information can differ from typical glvalues(lvalues and xvalues) to allow
for this instantiation to be smoother. For example, an implementation may
decide to focus on optimizations for merging multiple branches into one,
for which instead of branching the second type_set(selector) instantiates
into T^, it copies all the necessary information of type_set(selector) into
T^ at instantion and branches when ever it thinks T^ should branch. For
example:
{1, 2, 2.2} selector(int);
Type_set(selector) X=Selector(1);
Type_set(selector) Y=Selector(2);
Int a= X+Y+X*Y;
During every addition or multiplication, a branch would happen, but if the
compiler wants, it can delay branching that should have happened at the
instantiation of type_set(selector) into T^, and instead copy
type_set(selector) into every T^, and then branches based of that. This can
of course be one of many techniques implementation can choose to focus on
based on the computer architecture and the specializations of the hardware
of that time(for example if the ram has high bandwidth and more space to
spare or not to copy type_select(selector) into every T^).
In short, ***a summary is***:
1.Deferred Branching: Instead of branching at the declaration, the compiler
can treat T^ as a "variant-like" container that holds the state of the
selector.
2.Implementation-Defined Representation: As you noted in (1.1), T^ can have
a layout optimized for the specific architecture (e.g., leveraging high RAM
bandwidth to copy state rather than performing expensive CPU branching).
3.Preserving Zero Overhead: If you modify lvalues to support this behavior,
every existing C++ function using lvalues by value or reference would
potentially incur the cost of checking for "selector based" data. T^ keeps
this overhead for those willing to use heterogeneous lists.This also proves
my point that by inventing newer expression types, you are trying not to
hurt the existing features. It's like expanding your house horizontally
means you don't have to make the lower floors strong, but vertically does,
so adding newerr features is horizontal expansion, while expanding older
ones is vertical.

>"easy to implement" no it isn't, adding new value category can be
effective breaking change that will affect every code as for example:

```
>struct Foo
{
   void bar() &;
   void bar() &&;
};
```

>Now its need `void bar() ^;` too.

***ANSWER***
No, I said it multiple times that T^ can decay into T& or T&& or even T if
T^ overload doesn't exist. You don't need that. The decaying priority list
is as follows:
If const lvalue overload is there then const lvalue, if lvalue overload
then lvalue, if const lvalue reference overload then const lvalue, and so
on (for rvalues as well). This priority list makes overloading for T^ fit
right into the existing overloading rules, without having to make
additional complicated overloading rules.

>No, you add a new version of it and do not answer how it interacts
with old ones. Did you ever read how complex is overload resolution in
C++?
Read it and add this `^` without breaking it:

>https://en.cppreference.com/w/cpp/language/overload_resolution.html

>here you have some simplified version of it (I do not know how
accurate it is to standard text but probably a good approximation)
Could you show in that text where your `T^` will fit?

***ANSWER***
1. For most cases, overload resolution is that tough.
2. It will fit right in:
1. The reason that I said T^ decays into const T first, if that isn't
provided then T, and so on, is to simply the existing rules. Again the rest
of the rules remain the same. The decaying hierarchy is to simplify this
exact matter.
>> I said:The answer is that if type_set(selector) were to instantiate into
something else(lvalue), the compiler might have had to modify how lvalues
work. I want to keep them separate.

>He asked:again, modify what exactly?
****ANSWER****
Go to "($$$$1.1$$$$)"(control f then enter: ($$$$1.1$$$$) )




On Wed, 8 Apr 2026, 6:59 am Muneem, <itfllow123_at_[hidden]> wrote:

>
> Just to get my previous email to proposal list:
> >I do not know if you know how it will work, you again repeat nearly
> the same text without addressing the question.
> You name `T^` as an expression but you use this symbol only as a type
> of argument of template function, and this is not an expression.
> Please stop using terms that you do not know what they mean.
> Besides, why not use there normal `T&`? You break the whole overload
> resolution, drill hole in value categories for what exactly?
> Which one should be chosen: `Derived&` or `Base^` overload or opposite
> `Derivad^` or `Base&`?
> What is the difference between `T&` and `T^` on assembly level? What
> can I do with `T^` that is impossible with `T&`?
> >`type_set` is pointless, it should be same as `decltype(comtainer_obj)`
> ***ANSWER***
> 1. I NAMED T^ as in for ever T in the heterogeneous list, but sorry if I
> didn't convey my point properly.
> 2. The new value type T^ for every T is important because people may not
> be comfortable to add certain types in heterogeneous lists, like I may feel
> uncomfortable to add cookies in my heterogeneous lists because someone
> might steal them.
> 3. The new T^ is important because it is what type_set(selector) decays
> into, If I had said that type_set(selector) decays to a T lvalue or a T
> xvlaue then that would require some modifications to them which would break
> the zero overbead principle. Basically the goal was that it should be easy
> to implement, by making it completely separate. once instantiation is done
> then only can T^ mix into T&. The goal in short was to not drill a whole by
> mixing current expression types, but rather make a new one that every
> implementation can treat for this specific goal of instantion.
> 4. You asked:
> >Which one should be chosen: `Derived&` or `Base^` overload or opposite
> `Derivad^` or `Base&`?
> Replace Base^ and derived^ with rvalue references and then you know.
> Basically the overload resolution is the same, it's just another value type.
> 5. T^ is not different on a assembly level, it just helps user provide
> overloads for it, and the compiler to instantiate type_set(selector) into
> it. The mechanics of T^ is implementation defined, In that how
> type_set(selector) instnatiates into T^ is implementation defined, why?
> The answer is that if type_set(selector) were to instantiate into
> something else(lvalue), the compiler might have had to modify how lvalues
> work. I want to keep them separate.
> >To recap expresion is `1` or `1 + 2` or `foo()`, something `T&` like
> in `void foo(T& a)` is some kind of type. Again please do use terms
> you know what they mean exactly otherwise you will confuse yourself
> and everyone else who is trying to read your proposal.
> ***ANSWER***
> 1. Again, I am sorry for mixing terms, but it's an expression type in a
> sense that when type_set(selector) object is used then it instnatiates into
> T^ expression type for a T. When a function takes T^ for some T then it's a
> object type. The semantics for T^ is the same as lvalues, it's just useful
> for overloads as I described earlier.
>
> On Wed, 8 Apr 2026, 6:11 am Marcin Jaczewski, <marcinjaczewski86_at_[hidden]>
> wrote:
>
>> śr., 8 kwi 2026 o 02:27 Muneem <itfllow123_at_[hidden]> napisał(a):
>> >
>> > >I do not know if you know how it will work, you again repeat nearly
>> > the same text without addressing the question.
>> > You name `T^` as an expression but you use this symbol only as a type
>> > of argument of template function, and this is not an expression.
>> > Please stop using terms that you do not know what they mean.
>> > Besides, why not use there normal `T&`? You break the whole overload
>> > resolution, drill hole in value categories for what exactly?
>> > Which one should be chosen: `Derived&` or `Base^` overload or opposite
>> > `Derivad^` or `Base&`?
>> > What is the difference between `T&` and `T^` on assembly level? What
>> > can I do with `T^` that is impossible with `T&`?
>> > >`type_set` is pointless, it should be same as `decltype(comtainer_obj)`
>> > ***ANSWER***
>> > 1. I NAMED T^ as in for ever T in the heterogeneous list, but sorry if
>> I didn't convey my point properly.
>> > 2. The new value type T^ for every T is important because people may
>> not be comfortable to add certain types in heterogeneous lists, like I may
>> feel uncomfortable to add cookies in my heterogeneous lists because someone
>> might steal them.
>>
>> What on earth is arguing for "comfortable"?? I ask for technical
>> reasons why you need things like this and this is not the answer.
>>
>> > 3. The new T^ is important because it is what type_set(selector) decays
>> into, If I had said that type_set(selector) decays to a T lvalue or a T
>> xvlaue then that would require some modifications to them which would break
>> the zero overbead principle.
>>
>> What modifications?
>>
>> > Basically the goal was that it should be easy to implement, by making
>> it completely separate. once instantiation is done then only can T^ mix
>> into T&. The goal in short was to not drill a whole by mixing current
>> expression types, but rather make a new one that every implementation can
>> treat for this specific goal of instantion.
>>
>> "easy to implement" no it isn't, adding new value category can be
>> effective breaking change that will affect every code as for example:
>>
>> ```
>> struct Foo
>> {
>> void bar() &;
>> void bar() &&;
>> };
>> ```
>>
>> Now its need `void bar() ^;` too.
>>
>> > 4. You asked:
>> > >Which one should be chosen: `Derived&` or `Base^` overload or opposite
>> > `Derivad^` or `Base&`?
>> > Replace Base^ and derived^ with rvalue references and then you know.
>> Basically the overload resolution is the same, it's just another value type.
>>
>> No, you add a new version of it and do not answer how it interacts
>> with old ones. Did you ever read how complex is overload resolution in
>> C++?
>> Read it and add this `^` without breaking it:
>>
>> https://en.cppreference.com/w/cpp/language/overload_resolution.html
>>
>> here you have some simplified version of it (I do not know how
>> accurate it is to standard text but probably a good approximation)
>> Could you show in that text where your `T^` will fit?
>>
>> > 5. T^ is not different on a assembly level, it just helps user provide
>> overloads for it, and the compiler to instantiate type_set(selector) into
>> it. The mechanics of T^ is implementation defined, In that how
>> type_set(selector) instnatiates into T^ is implementation defined, why?
>> > The answer is that if type_set(selector) were to instantiate into
>> something else(lvalue), the compiler might have had to modify how lvalues
>> work. I want to keep them separate.
>>
>> again, modify what exactly?
>>
>> > >To recap expresion is `1` or `1 + 2` or `foo()`, something `T&` like
>> > in `void foo(T& a)` is some kind of type. Again please do use terms
>> > you know what they mean exactly otherwise you will confuse yourself
>> > and everyone else who is trying to read your proposal.
>> > ***ANSWER***
>> > 1. Again, I am sorry for mixing terms, but it's an expression type in a
>> sense that when type_set(selector) object is used then it instnatiates into
>> T^ expression type for a T. When a function takes T^ for some T then it's a
>> object type. The semantics for T^ is the same as lvalues, it's just useful
>> for overloads as I described earlier.
>> >
>> >
>> > On Tue, 7 Apr 2026, 5:29 pm Marcin Jaczewski, <
>> marcinjaczewski86_at_[hidden]> wrote:
>> >>
>> >> wt., 7 kwi 2026 o 05:23 Muneem <itfllow123_at_[hidden]> napisał(a):
>> >> >
>> >> > My response Mr.thiago and Mr.Marcin
>> >> >
>> >> > Before my response, let me summarize my proposal in the shortest
>> possible words:
>> >> > A implementation defined container type that holds an object of type
>> "type_set(container_object)". When
>> >> > ever any type_set(container_object) is used for any container_object
>> of this type, then it instantiates into T^(syntax can be something else for
>> T^). So passing typeset to a function, will call the overload for T^,
>> unless it isn't defined(some other is). T^ is a new expression type that's
>> a subset glvalue, but overloads that use T^ hold a reference to that
>> object. type_set(container_object) is a completelt new expression type,
>> when it decays into T^, the compiler instantiates all code. You may
>> disagree the need for T^, but I think it will help users overload and see
>> it coming.A variable can be of type type_set(comtainer_obj), in which case
>> the user if it will lead to instnatiation. This makes code easy to reason
>> about and deal with.
>> >> >
>> >>
>> >> I do not know if you know how it will work, you again repeat nearly
>> >> the same text without addressing the question.
>> >> You name `T^` as an expression but you use this symbol only as a type
>> >> of argument of template function, and this is not an expression.
>> >> Please stop using terms that you do not know what they mean.
>> >> Besides, why not use there normal `T&`? You break the whole overload
>> >> resolution, drill hole in value categories for what exactly?
>> >> Which one should be chosen: `Derived&` or `Base^` overload or opposite
>> >> `Derivad^` or `Base&`?
>> >> What is the difference between `T&` and `T^` on assembly level? What
>> >> can I do with `T^` that is impossible with `T&`?
>> >>
>> >> `type_set` is pointless, it should be same as `decltype(comtainer_obj)`
>> >>
>> >>
>> >> >
>> >> > Mr.marcin said:
>> >> > Then do not use random symbols.
>> >> > ****ANSWER****
>> >> > I used random symbols so I don't have to say "the new expression
>> type 2", but if you have any better name, please please tell me to use that.
>> >> >
>> >>
>> >> To recap expresion is `1` or `1 + 2` or `foo()`, something `T&` like
>> >> in `void foo(T& a)` is some kind of type. Again please do use terms
>> >> you know what they mean exactly otherwise you will confuse yourself
>> >> and everyone else who is trying to read your proposal.
>> >>
>> >> > Mr.thiagi said:
>> >> > >This is not about what the community wants. You're the one
>> proposing. You can
>> >> > incorporate feedback as it comes. But an incomplete proposal will
>> only get us
>> >> > going around in circles because we don't see the full picture.
>> >> >
>> >> > And you need to be familiar with C++ enough to understand that JIT
>> is not
>> >> > going to be acceptable without our having to say so.
>> >> >
>> >> > ****Answer****
>> >> > 1. I did try to propose a new value type type but you guys propose
>> other techniques, hence I tried again, but this went slowly. Sorry if this
>> technique caused confusion.
>> >> > 2. The community did not want values,templates, or operator
>> overloads, not because it was useless, but because no other language (or
>> very few) has them.
>> >> > 3. I use JIT just as an example on why feedback is important to
>> correct one mistakes. In fact, there have been research papers on why JIT
>> would help C++, but the reason templates or polymorphism in general doesn't
>> incorporate them is because of community feedback. Instead other techniques
>> are used.
>> >> >
>> >> >
>> >> > On Tue, 7 Apr 2026, 7:23 am Marcin Jaczewski, <
>> marcinjaczewski86_at_[hidden]> wrote:
>> >> >>
>> >> >> wt., 7 kwi 2026 o 03:08 Muneem via Std-Proposals
>> >> >> <std-proposals_at_[hidden]> napisał(a):
>> >> >> >
>> >> >> > My response to Mr.Sebistian.
>> >> >> > (Note: I use T^ just as an example of the name, the real name
>> would again be up to you guys because I can't make a judgment on syntax
>> with limited experience)
>> >> >>
>> >> >> Then do not use random symbols.
>> >> >>
>> >> >> > >To keep it simple and stay at the problem once again:
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> > >From a std::tuple<T, U, V>
>> >> >> >
>> >> >> > >you want to select an element by index (possibly runtime)
>> >> >> >
>> >> >> > >it returns something like std::variant<T, U, V>, but perhaps with
>> >> >> >
>> >> >> > - better support of references
>> >> >> >
>> >> >> > - storing the index used for selection
>> >> >> >
>> >> >> > - custom operation wrappers
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> > >That std::variant like type allows (common) operations to be
>> called on.
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> > >In current C++ I would create a class (UR is a custom class, not
>> inside the standard library):
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> > class Dispatch
>> >> >> >
>> >> >> > {
>> >> >> >
>> >> >> > public:
>> >> >> >
>> >> >> > Dispatch(tuple<A, B, C> t, int index);
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> > void op1();
>> >> >> >
>> >> >> > void op2();
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> > tuple<A, B, C>& _tupleref;
>> >> >> >
>> >> >> > int _index;
>> >> >> >
>> >> >> > }
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> > >Then the compiler has anything it needs for optimization. What
>> is missing compared to your solution?
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> > tuple<A, B, C> t = { a, b, c }; // initialize
>> >> >> >
>> >> >> > Dispatch<A, B, C> d(t, i); // select index i
>> >> >> >
>> >> >> > i.op2(); // call operations
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> > >No need for new categories or value types or new syntax?
>> >> >> >
>> >> >> > >Full flexibility for customization.
>> >> >> >
>> >> >> > >Full optimization potential.
>> >> >> > ****ANSWER****
>> >> >> > 1. As I said the new T^ would allow for the user to see elements
>> of type T in heterogeneous list coming.
>> >> >> > 2. I updated my proposal (in my last email to Mr.thiago) to have
>> a new type other T^, that is different (and more type safe) than
>> std::variant.
>> >> >>
>> >> >> This is nowhere close response to Sebastian example. You only repeat
>> >> >> what you already previously said not addressing this example in any
>> >> >> way.
>> >> >> If this `T^` is type, what EXACTLY does it have? And how its even
>> >> >> possible to have type more type safe than `std::variant`?
>> >> >>
>> >> >> > ****Limitations in your example****
>> >> >> > 1. I can't pass an element from the tuple in your example to a
>> function,
>> >> >>
>> >> >> `Dispatch` can be pass around, and as far I understand it was the
>> >> >> point of Sebastian's example.
>> >> >>
>> >> >> > and expect an instantion from type_set(selector) to T^(as in my
>> case) which can further decay into T or T& or T&&. This is important
>> because without this feature your elements in tuple are stuck, and can be
>> passed to a function based on runtime indexes without switch statements
>> that I am guessing dispatch already has to use.
>> >> >>
>> >> >> And how its diffrent to `T^`? You too need have somewhere runtime
>> >> >> index. Where it is?
>> >> >>
>> >> >> > 2. Compiler can't use additional book keeping for the switch case
>> statements that you are using in dispatch because of the zero overhead
>> Principe limiting tuples to be tuples instead of runtime indexed
>> heterogeneous lists.
>> >> >>
>> >> >> And what bookkeeping is supposedly needed there? I can easily image
>> >> >> all needed parts in Sebastian and I do not see any missing bits that
>> >> >> could prevent usage of it. Do you analyze it, or even try to use it
>> or
>> >> >> dismiss it without even understanding how it works?
>> >> >>
>> >> >> > 3. You cant assign/move to the element that
>> >> >> > d.index is pointing to. While in my case you can (refer to my
>> last response to Mr. Thiago:
>> https://lists.isocpp.org/std-proposals/2026/04/17675.php), to see the
>> additional expression value type that I proposed.
>> >> >> >
>> >> >>
>> >> >> No, it can, same as your type where you throw an exception if types
>> do
>> >> >> not match.
>> >> >> It can be easily implemented by user defined assignment and in it
>> >> >> check if index point to correct type.
>> >> >>
>> >> >> >
>> >> >> >
>> >> >> > On Mon, 6 Apr 2026, 4:04 pm Sebastian Wittmeier via
>> Std-Proposals, <std-proposals_at_[hidden]> wrote:
>> >> >> >>
>> >> >> >> To keep it simple and stay at the problem once again:
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >> From a std::tuple<T, U, V>
>> >> >> >>
>> >> >> >> you want to select an element by index (possibly runtime)
>> >> >> >>
>> >> >> >> it returns something like std::variant<T, U, V>, but perhaps with
>> >> >> >>
>> >> >> >> - better support of references
>> >> >> >>
>> >> >> >> - storing the index used for selection
>> >> >> >>
>> >> >> >> - custom operation wrappers
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >> That std::variant like type allows (common) operations to be
>> called on.
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >> In current C++ I would create a class (UR is a custom class, not
>> inside the standard library):
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >> class Dispatch
>> >> >> >>
>> >> >> >> {
>> >> >> >>
>> >> >> >> public:
>> >> >> >>
>> >> >> >> Dispatch(tuple<A, B, C> t, int index);
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >> void op1();
>> >> >> >>
>> >> >> >> void op2();
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >> tuple<A, B, C>& _tupleref;
>> >> >> >>
>> >> >> >> int _index;
>> >> >> >>
>> >> >> >> }
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >> Then the compiler has anything it needs for optimization. What
>> is missing compared to your solution?
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >> tuple<A, B, C> t = { a, b, c }; // initialize
>> >> >> >>
>> >> >> >> Dispatch<A, B, C> d(t, i); // select index i
>> >> >> >>
>> >> >> >> i.op2(); // call operations
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >> No need for new categories or value types or new syntax?
>> >> >> >>
>> >> >> >> Full flexibility for customization.
>> >> >> >>
>> >> >> >> Full optimization potential.
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >>
>>
>

Received on 2026-04-08 02:22:25