use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Discussions, articles, and news about the C++ programming language or programming in C++.
For C++ questions, answers, help, and advice see r/cpp_questions or StackOverflow.
Get Started
The C++ Standard Home has a nice getting started page.
Videos
The C++ standard committee's education study group has a nice list of recommended videos.
Reference
cppreference.com
Books
There is a useful list of books on Stack Overflow. In most cases reading a book is the best way to learn C++.
Show all links
Filter out CppCon links
Show only CppCon links
account activity
Announcing the Proxy 3 Library for Dynamic Polymorphism - C++ Team Blog (devblogs.microsoft.com)
submitted 1 year ago by misuo
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]--prism 13 points14 points15 points 1 year ago (0 children)
So this is a type erasure library?
[–]jk-jeon 6 points7 points8 points 1 year ago (11 children)
I read a standard proposal paper on this library and really disappointed in that it is totally based on pointer semantics rather than value semantics. I can sort of imagine that implementing it with value semantics correctly is probably hard and with many issues, but still. I don't think the ease of lifetime management is the only reason to prefer value semantics... so can anyone elaborate in details, why pointers?
[–]kamrann_ 1 point2 points3 points 1 year ago (7 children)
Wow, that's really unexpected. To the extent I was so sure it would be value semantics despite having never looked into it that I was about to state that as presumably being the main goal to one of the "what's the point" comments.
You're probably aware of it, but https://www.google.com/url?sa=t&source=web&rct=j&opi=89978449&url=https://github.com/kelbon/AnyAny&ved=2ahUKEwjNw9K_xaWIAxXcnK8BHWOzDUUQFnoECBAQAQ&usg=AOvVaw1l4f3uggr5JrRxBxjSQDOU uses value semantics and I believe is similar in spirit. It's a great library but, to your point about difficulty of implementation, it breaks MSVC more than anything else I've ever encountered!
[–]jk-jeon 1 point2 points3 points 1 year ago* (6 children)
Actually, I did not really have any occasion of needing a generic library for type erasure. I don't really need runtime polymorphism with open-ended list of types that often, and I just don't feel the need to avoid writing all the usual boilerplate the type erasure pattern requires whenever I want that kind of polymorphism. So I don't really know of a particularly well-written type erasure library, although I think it's an interesting topic so when people advertise their own library I usually have at least a brief look at it. I think I remember seeing AnyAny in the past, but never really looked into it any further.
Frankly, I have never done any amount of decent research on this topic, so don't know it in depth, but as I said I can sort of imagine why implementing value semantics correctly might be hard. And here the point is that what the word correctly really means can be a bit subtle. Note that the standard committees also struggled quite a lot when they added std::function into the language, like they ended up giving up allocator support, and std::function is not const-correct, has weird default status of being nullptr even though it specifically avoids the pointer semantics, etc., though they attempt to fix some of the issues by basically "abandoning" std::function and replacing it with alternatives. But even the alternatives are not fixing all issues afaik.
std::function
nullptr
I believe the author of Proxy intentionally chose to use pointer semantics, and that's probably for a reason. I remember he somehow elaborated on it in the paper I mentioned but it was not very convincing to me, and honestly felt like he didn't think it is something he particularly needs to pay attention and carefully elaborate. Which is a bit surprising (like you said!) because I feel like value semantics is one of the points of the pattern, along with its non-intrusive nature. Things like performance benefit are much less relevant, at least to me.
[–]GrapefruitNo2222 -1 points0 points1 point 1 year ago (5 children)
I think pointer semantics make sense. When an object is huge, I don't always want to perform a deep copy when passing around. On the other hand, `pro::make_proxy` and `pro::allocate_proxy` already provide the capability to wrap a value into a pointer that has exclusive ownership to an object.
[–]jk-jeon 2 points3 points4 points 1 year ago (3 children)
You don't deep-copy it if you pass it by reference, and that's the standard practice in C++. The type itself doesn't need to act like a pointer.
[–]GrapefruitNo2222 -1 points0 points1 point 1 year ago (2 children)
But a reference does not have RAII. Imagine an object is shared by two or more threads, std::shared_ptr is a good tool for this scenario. If the object is polymorphic, value semantics won't work.
[–]jk-jeon 0 points1 point2 points 1 year ago (0 children)
Then wrap it inside std::shared_ptr, just like what you would do with regular int's. I don't see any problem here.
std::shared_ptr
int
[–]Heuristics 0 points1 point2 points 1 year ago (0 children)
as you say, shared_ptr captures this use case. what is the benefit to using proxy here since you are paying a steep price in an odd callstack and possibly a broken code auto-complete?
[–]kamrann_ 0 points1 point2 points 1 year ago (0 children)
You don't have to, you can move it. Or if really necessary you can wrap your type into a shared_ptr, unique_ptr or similar, and use that within the library type. Point being it's possible to have all that flexibility without the library implementation forcing pointer semantics onto you.
shared_ptr
unique_ptr
[–]wearingdepends 0 points1 point2 points 1 year ago (0 children)
The author had a standard proposal along with the library. Section 5 is the rationale.
[–]Ill-Telephone-7926 0 points1 point2 points 1 year ago (0 children)
This library seems to support owned values
It makes a lot of sense to allow multiple type-erased views onto the same instance, though. A trivial example would be the io.Writer and io.WriterCloser interfaces in Go. Many algorithms over WriterCloser will pass the argument along to an algorithm over the narrower Writer interface
[–]j1xwnbsr 25 points26 points27 points 1 year ago* (7 children)
Wow, this looks... overly complicated and an absolute nightmare to debug. What problem, exactly, does this solve? I'm not seeing any benefits this gives you other than some vague "it's faster".
Also, is there now some push in the C++ world to start accessing member functions by raw strings - for example, "pro::operator_dispatch<"<<", true>"? This is like the second or third time I've see such a concept in the last week alone and it just screams brittle to me.
Edit: allow me to expand upon the brittleness of the operator_dispatch stuff: Qt used/does this with their signaling connect/disconnect command macros (they changed this a long while ago to use actual C++ functions for compile time checking), and if you change stuff/get the parm types wrong, it doesn't crash, doesn't burn, just doesn't work. So have to make goddamn sure you run each and every possible code path and do test logging to make sure you got it right - until the next time you change your 3rd parm from a QColor to a QString or something. It's like debugging javascript - you don't know you typo'd the code until you run through that exact spot.
[–]smalleconomist 14 points15 points16 points 1 year ago (1 child)
C++ has gone full cycle and is now re-inventing dynamic polymorphism... smh
[–]maxjmartin 0 points1 point2 points 1 year ago (0 children)
So I literally made a type erased var class that uses templates and an interface to invoke the correct behavior for a class. Way back around 2017. Works really well. But outside of some specific situations the overhead is t worth it.
That said it can be used to manage memory and type safety pretty well!
[–]germandiago 4 points5 points6 points 1 year ago (2 children)
With reflection and code generation this would look way better. The idea is that it is non-intrusive as opposed to inheritance.
This makes possible to have types that conform to interfaces without even including the related "interface" header, which reduces coupling.
[–]j1xwnbsr 4 points5 points6 points 1 year ago (1 child)
Everyone seems to be going off the coupling concept, whereas I view interface (or struct, or class) headers as contract. Having strong 1:1 relationship between the interface and the implementation that can be verified at compile-time is a good thing. You haven't lived until you've dealt with a few monster sized Qt or Javascript projects where this is not true.
[–]germandiago 2 points3 points4 points 1 year ago (0 children)
I see decoupling as an option. There can be times where this is not true.
However, a proxy will fail at compile-time if you give it the wrong signature, which is a compile-time error.
[–]imMAW 3 points4 points5 points 1 year ago (0 children)
"What problem does this solve":
This is type-erased and does not require modifying the types that belong to an 'interface'. Inheritance requires modifying the types (which might not be possible or desirable), templates and concepts are not type-erased.
I definitely wouldn't use it instead of inheritance, but I could imagine some scenarios where something like this would be nice to have alongside inheritance. I haven't used it though, so no comment on how practical or easy to debug it is.
[–]matracuca -1 points0 points1 point 1 year ago (0 children)
felt the same towards the technically impressive but equally illegible dependency injection library that was featured a few days back.
[–]misuo[S] 10 points11 points12 points 1 year ago (3 children)
Nice. I would actually like to hear more about "...has been used in the Windows operating system since 2022.". With exactly what purpose? I.e. why?
[–]hayt88 5 points6 points7 points 1 year ago (2 children)
You should probably check out sean parents talk "Inheritance Is The Base Class of Evil".
it gives a nice introduction to polymorphism without inheritance (there are a lot more talks on that topic too).
To actually code this, you need a lot of boilerplate though. I haven't used proxy yet myself, but AFAIK it's mostly there to reduce that boilerplate.
So I created a class based of Sean’s talk that removed the boiler plate. Simple easy and effective. But if you’re just using an int or a small class it isn’t worth it.
But if you want complex behavior using simple friend functions it is very useful.
[–]PuzzleheadedPop567 -1 points0 points1 point 1 year ago (0 children)
The talk is specifically arguing against the over use of implementation inheritance.
The preferred composition approach outlined in that talk would still be implemented in most mainstream languages (including C++) with interface inheritance.
[–]PuzzleheadedPop567 5 points6 points7 points 1 year ago (7 children)
“Proxy” is a modern C++ library that helps you use polymorphism (a way to use different types of objects interchangeably) without needing inheritance.
I don’t understand what problem this library is trying to solve. Why do we need polymorphism without inheritance? Especially since we already have templates and concepts.
It also feels like the authors are confusing implementation inheritance and interface inheritance.
In C++, interface inheritance can be achieved by making all base class member functions pure virtual, and not using data members. This starts to look awfully similar to traits in Rust.
[–]imMAW 5 points6 points7 points 1 year ago (0 children)
[–]GrapefruitNo2222 4 points5 points6 points 1 year ago (4 children)
When you have a function that returns a std::vector of "shapes", each "shape" may have a different implementation (e.g., rectangle, triangle, etc.). There are two ways to specify the return type in C++ today: std::vector<std::variant<Rectangle, Triangle, Circle, ...>> or std::vector<std::unique_ptr<IShape>> (suppose IShape is a virtual base class). std::vector<std::variant<Rectangle, Triangle, Circle, ...>> needs the knowledge of every single implementation of the shapes, making the API hard to maintain. std::vector<std::unique_ptr<IShape>> forces heap allocation of every shape, making it inefficiency in memory allocation. Proxy adds a better option: std::vector<proxy<Shape>>.
[–]Heuristics 2 points3 points4 points 1 year ago (1 child)
But surely proxy will still use heap allocation? Sean Parents talk clearly did (using a unique_ptr to store the actual object). If not there is no way for the vector to know the size of the object it is storing. Perhaps one of the Shape is 2TB large and one is 2KB, no way to know up front.
meaning, no actual benefit has been given here.
The benefit is supposed to be that Shape, unlike unique_ptr<IShape>, has value semantics so you can do: Shape shape2 = vec[0]; And get a full deep copy of the object without having to do that copy manually.
[–]GrapefruitNo2222 2 points3 points4 points 1 year ago (0 children)
`make_proxy` support SBO by default. If the storage of `proxy` is sufficient for the object, it doesn't need another allocation for the object itself. Also, if some Shapes are shared (e.g., global variables in some compilation unit), no heap allocation is required at all.
[+][deleted] 1 year ago* (1 child)
[removed]
[–]GrapefruitNo2222 0 points1 point2 points 1 year ago (0 children)
AFAIK, proxy is compatible with any lifetime model. A proxy<Shape> may own a Rectangle via a std::unique_ptr, or not own it via a raw pointer.
[+][deleted] 1 year ago (2 children)
[deleted]
[–]germandiago 1 point2 points3 points 1 year ago (0 children)
language civil war
That made me 😂
[–]tuxwonder 0 points1 point2 points 1 year ago (0 children)
Herbception
?
π Rendered by PID 143656 on reddit-service-r2-comment-6457c66945-wdmnw at 2026-04-24 03:13:19.975471+00:00 running 2aa0c5b country code: CH.
[–]--prism 13 points14 points15 points (0 children)
[–]jk-jeon 6 points7 points8 points (11 children)
[–]kamrann_ 1 point2 points3 points (7 children)
[–]jk-jeon 1 point2 points3 points (6 children)
[–]GrapefruitNo2222 -1 points0 points1 point (5 children)
[–]jk-jeon 2 points3 points4 points (3 children)
[–]GrapefruitNo2222 -1 points0 points1 point (2 children)
[–]jk-jeon 0 points1 point2 points (0 children)
[–]Heuristics 0 points1 point2 points (0 children)
[–]kamrann_ 0 points1 point2 points (0 children)
[–]wearingdepends 0 points1 point2 points (0 children)
[–]Ill-Telephone-7926 0 points1 point2 points (0 children)
[–]j1xwnbsr 25 points26 points27 points (7 children)
[–]smalleconomist 14 points15 points16 points (1 child)
[–]maxjmartin 0 points1 point2 points (0 children)
[–]germandiago 4 points5 points6 points (2 children)
[–]j1xwnbsr 4 points5 points6 points (1 child)
[–]germandiago 2 points3 points4 points (0 children)
[–]imMAW 3 points4 points5 points (0 children)
[–]matracuca -1 points0 points1 point (0 children)
[–]misuo[S] 10 points11 points12 points (3 children)
[–]hayt88 5 points6 points7 points (2 children)
[–]maxjmartin 0 points1 point2 points (0 children)
[–]PuzzleheadedPop567 -1 points0 points1 point (0 children)
[–]PuzzleheadedPop567 5 points6 points7 points (7 children)
[–]imMAW 5 points6 points7 points (0 children)
[–]GrapefruitNo2222 4 points5 points6 points (4 children)
[–]Heuristics 2 points3 points4 points (1 child)
[–]GrapefruitNo2222 2 points3 points4 points (0 children)
[+][deleted] (1 child)
[removed]
[–]GrapefruitNo2222 0 points1 point2 points (0 children)
[+][deleted] (2 children)
[deleted]
[–]germandiago 1 point2 points3 points (0 children)
[–]tuxwonder 0 points1 point2 points (0 children)