C++ Logo

std-proposals

Advanced search

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

From: Sebastian Wittmeier <wittmeier_at_[hidden]>
Date: Wed, 8 Apr 2026 09:55:32 +0200
You are very adamant that the selected element of the tuple should be allowed to be copied out of the tuple, be used as a function parameter and not use pointers or references.   But then you potentially go through an ABI boundary. That means you have to specify and fix, what is transferred at the function call. There is no more optimization flexibility for the compiler.   In your case you want to copy the tuple element -> you get something like a variant (or your version of it). Perhaps with the added knowledge, which functions can be called (the common functions of the type list in the tuple). You could create and pass function pointers for those at the call site, but I think that would not be performant. Or would it in your case?   Or you state the optimizations don't work well through an ABI boundary? Fair enough. It has to be in a single translation unit or it needs link-time-optimization. But then you get similar code from my Dispatch class or a similar construct, because the optimizer can remove all overhead.   Just be clear how it would work. With an ABI boundary and without. With an ABI boundary you need a fixed specification, what is transmitted (no high level concepts, but in a binary sense), without an ABI boundary many more solutions (even those without any change to the language) would lead to identical code.   -----Ursprüngliche Nachricht----- Von:Muneem via Std-Proposals <std-proposals_at_[hidden]> Gesendet:Mi 08.04.2026 02:00 Betreff:Re: [std-proposals] Fwd: Extension to runtime polymorphism proposed An:std-proposals_at_[hidden]; CC:Muneem <itfllow123_at_[hidden]>;  Before my response to Mr.sebistian and Mr. Simon: Small correction in my last emai(the change is in point 3): 1. The compiler can use a union, which case you have that advantage of the feature "potential merging multiple branches" that I talked about in my previous email. 2. The compiler can cause a function call after each definition 3.The compiler can do one of those, the second the variable is used or when the element has changed, the compiler can also choose the best point for instantion in between the varianle.defintion and when one of the two things happen. 4.will never do one of those if the list is filled only with const qualified types ( don't know if it's a good idea yet because of user defined types. 5.Again, in usage it will decay into T^, which can turn into at T& or T&&, so you can copy or move from it.   ****Small recap*****: Basically the issue with tuples and this: (The mr mr.sebistian thinks it should work for heterogeneous lists): class Dispatch { public:     Dispatch(tuple<A, B, C> t, int index);     void op1();     void op2();     tuple<A, B, C>& _tupleref;     int _index; }; tuple<A, B, C> t = { a, b, c }; // initialize Dispatch<A, B, C> d(t, i); // select index i i.op2(); // call operations ***Issues*** 1.How do you get a tuple elements out, how do you get a tuple elements std::plus any type out. One way is to use variants, but then the variant returned can be assigned any type, which is again type safe. If I get an object of type A from the tuple or after adding the element at index 0 with another B, then I should not be able to assign B to it. That's not how type safe c++ is supposed to be. The same issue exists for a array of variants  2.It takes a type T^, why is that an issue? Well, I may not be comfortable adding certain types in a list, for example for a bunch of representing a http packet, I may not be willing to have cookies in this list. The same applies to many users of heterogenous lists. Normal tuples won't allow me to put them in tuples and expect a special "safe" overload be called for them. In my proposals case, the overload will be that if T^; it fixes the downsides of the flexibility that heterogeneous lists provide.   Response to Mr.Sebistian: >Just quickly answering 1)  >Would you rather have the whole tuple copied everytime?  >To the target stack frame? >In your proposed solution you can also copy a pointer to the role or the whole tuple (as long as the optimizer does not optimize over the function call).  ****Answer**** 1.No, it would leave it to the compiler, by having a implementation defined container for this reason. Sometimes copying a tuple is efficient sometimes not. Many times however you would want to move the tuple, and return it back. 2.In my proposal, since the container is implementation defined hence the compiler has a free hand in copying it however it wants and moving it however it wants.  3. I don't know what you mean by copying a role , but I think you meant pointing to an element using a point and copying that point.if yes: Then no you can't do that, you can't have pointers to type_set(selector) but can have points to T^, just like you can point to any other glvalue(T^) is a glvalue.      >It will be faster only for small tuples, which perhaps can be passed in registers. >But it is a simple change for Dispatch to store the tile instead of a pointer to the tuple. >If you want to use the select to make the tuple smaller for directly copying the tuple, then just store the selected element as a variant in the Dispatch object. ****ANSWER**** 1. No, my solution would be faster for heterogeneous list of any type because the compiler has full say in weather to copy it or not, and how to copy it, since the container is implementation defined. 2. What's a tile into the tuple? Please elaborate the thing that you mean by tile. 3. Variants don't have fixed types, hence for heterogeneous lists, they aren't an option at all. Even if say a A.dispatch(runtime index,std::plus, float{1}) return a variant that can have int, float, and I assign that variant to an object X of the same variant type, then object X can hold both float, int, but In heterogenous lists, I don't want that, I want the type to be fixed. So a tuple of built in types that have fixed types at each index is impossible, without the new value type type_set(selector). Where as in my solution, object: type_set(selector) X= selector(runtime_index) Can only hold what runtime_index was fixed to hold. So my proposal makes code more type safe and easy for reason about.     >With your proposal the compiler has to break down your constructs, too. It also has to pass something to functions (if ABI boundary and not optimized over function calls). If you can program the same with current C++ we can reason about it.  >I try to distill, what is actually new in your proposal. >That it also cannot be provided by one layer of C++, which would lead to the same assembly anyway, if it is equivalent to your proposed language extension. >Perhaps we find one small new language feature and another thing which can be expressed with some syntactic sugar. >A language feature can be interface like ad-hoc relationships between types with common member function signatures. >Otherwise perhaps 1 or 2 hints for the optimizer ****ANSWER**** 1.thats why I proposed new value types, so that the compiler can use the existing branching and template instantion mechanisms. The compiler won't have to do anything other than use the existing mechanisms more efficiently to index the heterogeneous list. It basically uses the existing features compilers have. Like it does not have to break down constructs, just implementation defined container to get the type_set(selector), and instnatiate it into every possible T^. Like again, we have a million branching techniques the compilers already have. 2. It's not just 2 or 3 optimizations: 1. It's better type safety : Type_set(selector) X= selector(runtime index) The element at runtime index was int then you CANT assign float to X. This is an issue that std::variants fails to address. You may want to modify std::variant but that would either need changing how unions work or produce new expression type that my proposal already does. 2. Extended metaprogramming capabilities by simply merging current branching and template mechanisms. 3. This can be provided by one layer of c++ because c++ already has templates and branching facilities.     You want to move code generation to the location of the final op call, you don't want to use pointers, but want to send only the needed information through function call or even ABI boundaries. ****ANSWER**** 1. I want code generation when ever type_set(selector) is used, and the compiler can merge the branches generated if it wants. I don't want to use pointers because again, they don't provide copy/move without having to allocate a new object all together or have the risk of slicing. 2. It's up to the compiler on what information to send for each branch.   My response to Mr.Simon: JSON and XML where the examples I have provided before. However, these only work if we have a runtime heterogeneous list. Until now (especially with your example from the Turing virtual machine) we were talking about heterogeneous lists known at compile time. The solutions to these problems differ a lot: at compile time we can just use std::tuple. However, if we want to modify a list at runtime we are back to std::vector<std::variant> (or something similar). With your most recent explanations we are closer to the latter. However, the most efficient solution in your case would work with a std::tuple rather than with a std::vector<std::variant>. If the types are fixed at compile time the compiler can optimize much better.  So, which one do you want? Compile time lists or runtime lists? (Runtime indices would be allowed in both cases.) ****ANSWER**** I want a compile time known implementation defined container of type type_set(selector for the reasons described in the "Small recap" recap section.   On Tue, 7 Apr 2026, 5:01 pm Simon Schröder via Std-Proposals, <std-proposals_at_[hidden] <mailto:std-proposals_at_[hidden]> > wrote:   On Tue, Apr 7, 2026 at 10:58 AM Muneem via Std-Proposals <std-proposals_at_[hidden] <mailto:std-proposals_at_[hidden]> > wrote: You may disagree for the need of T^ but again considering that heterogeneous lists will mostly be ever used in networking protocols, JSONs, XMLs, you want as the programmer to have a freehand in providing (application) safety, when you let a user index your list with any index he wants.   JSON and XML where the examples I have provided before. However, these only work if we have a runtime heterogeneous list. Until now (especially with your example from the Turing virtual machine) we were talking about heterogeneous lists known  at compile time. The solutions to these problems differ a lot: at compile time we can just use std::tuple. However, if we want to modify a list at runtime we are back to std::vector<std::variant> (or something similar). With your most recent explanations we are closer to the latter. However, the most efficient solution in your case would work with a std::tuple rather than with a std::vector<std::variant>. If the types are fixed at compile time the compiler can optimize much better.  So, which one do you want? Compile time lists or runtime lists? (Runtime indices would be allowed in both cases.) -- Std-Proposals mailing list Std-Proposals_at_[hidden] <mailto: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-08 07:56:45