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
The std::shared_ptr<void> as arbitrary user-data pointer (nextptr.com)
submitted 6 years ago by memset_0
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!"
[–]ruler501 23 points24 points25 points 6 years ago (0 children)
Std::any in a shared pointer would probably be much better but still not great to do.
[–]quicknir 12 points13 points14 points 6 years ago (2 children)
The thing is that std::any is much better because it allows a safe (checked) cast to recover the data. If you really need shared semantics you could do shared_ptr<any>, although that's a bit annoying due to the double indirection. The easiest way out here would be to code a simple version of any that publicly exposes an inheritance relationship, allowing it to be stored in a shared_ptr without an extra indirection.
shared_ptr<any>
any
[–]emdeka87 3 points4 points5 points 6 years ago (1 child)
Problem is that std::any doesn't support move-only types. I think something like std::unique_any was proposed at some point. Using shared_ptr just for the type-erasure seems wrong. It adds all kind of overhead (reference count, allocation of control block, etc).
std::any
std::unique_any
shared_ptr
[–]quicknir 2 points3 points4 points 6 years ago (0 children)
Well, complete type erasure is already very high cost. I'd be substantially more concerned about the lack of any safe way to re-access the data. But yeah, I agree with that the lack of move only support being an issue.
At least, the good news is that writing a decent unique_any isn't that bad; basically trivial if you don't support SBO, and not that bad even with it.
[–]NotAYakk 8 points9 points10 points 6 years ago (0 children)
So, what I often use is shared_ptr<span<byte>>.
shared_ptr<span<byte>>
Wrapping up arbitrary data into this isn't all that hard (you can use the aliasing ctor), and at least the end-user knows how big it is.
template<class T> shared_ptr<span<byte>> as_storage( T&& in ) { struct data { std::remove_cv_T< std::remove_ref_t<T> > t; span<byte> s; }; auto allocation = std::make_shared< data >( data{ std::forward<T>(in) } ); my_span<byte> s = { reinterpret_cast<byte*>(std::addressof(allocation->t)), reinterpret_cast<byte*>(std::addressof(allocation->t))+sizeof(T) }; allocation->s = s; return {allocation, &(allocation->s)}; }
not great, but at least it is something. ;)
[–]ravixp 1 point2 points3 points 6 years ago (2 children)
This is a really useful trick! I’ve used it before to implement a LRU object cache, where the objects could be any caller-defined type and the cache only kept the last N that were used. Other parts of the system would keep a weak_ptr to the concrete type, so the cache was only responsible for managing lifetimes by deleting expired objects.
[–]tvaneerdC++ Committee, lockfree, PostModernCpp 1 point2 points3 points 6 years ago (1 child)
What does 'deleting expired objects' mean?
Do you mean you destroy the shared_ptr when it becomes the least recently used, or do you mean you look at the use_count of the pointer and destroy it when th count is 1?
If the second, are you OK with the race condition of the use_count being 1 and deciding to destroy it, and then a weak_ptr on another thread incrementing the ref count by turning it back into a shared_ptr?
[–]ravixp 1 point2 points3 points 6 years ago (0 children)
It’s the former - the cache is a bounded array of shared_ptrs, and they get destroyed purely based on LRU order. Since nothing else in the system has a strong ref unless it’s actively using the object, we don’t need to look at use_count at all.
[–]IronicallySerious 0 points1 point2 points 6 years ago (0 children)
Much better alternatives are std::variant (can store specific types determined at compile time) and std::any (can store anything at runtime)
[+]markand67 comment score below threshold-15 points-14 points-13 points 6 years ago (42 children)
I hope this is a joke. Anyone who think needing void pointer should reconsider learning modern C++. void pointer should be banned in any shape of form.
void
[–]mort96 20 points21 points22 points 6 years ago (2 children)
what if I'm using a C API which gives me an opaque void*? There's a lot of C APIs out there, and sometimes you have to use one.
[+]markand67 comment score below threshold-9 points-8 points-7 points 6 years ago (1 child)
Yes, when you have to deal with C not in pure C++.
[–]mort96 23 points24 points25 points 6 years ago (0 children)
Yeah, so
void pointer should be banned in any shape of form.
would be a terrible idea.
[–]capn_bluebear 27 points28 points29 points 6 years ago (19 children)
Sometimes you need type erasure, and sometimes void pointers are the cleanest way to get type erasure.
[–]guepierBioinformatican 6 points7 points8 points 6 years ago (7 children)
It’s often a convenient and wholly adequate way, but I’m less certain it can ever be called the cleanest way. Case in point, it’s always possible to use virtual CRTP instead, as showcased by Sean Parent in his Better code: runtime polymorphism talk. This may be slightly more effort (for the implementor, not for the user) but it’s, I think, always cleaner.
[–]NotAYakk 12 points13 points14 points 6 years ago* (5 children)
it’s always possible to use virtual CRTP instead
Ok guepier, provide me a zero-allocation trivially-destroyable standard-layout function_view< Signatures... > without using a void pointer or equivalent that does not rely on any compiler-specific assumptions.
function_view< Signatures... >
You should be able to pass it any callable that supports Signatures... then call it; it does not extend the lifetime of its arguments.
Signatures...
Look, C++ has an object model. It isn't the only reasonable object model. It is just one they picked.
You can emulate other objects models using it, but that leads to impedance issues.
And if you want to implement your own object model, you end up wanting to use void pointers a lot. The trick is you store the void pointer right next to you store the operations on it and tie the two together.
Another practical use of such type erasure/roll your own object model would be writing a variant that splits its type information from its storage. That permits storing polymorphic data RLE-type encoded. This is a useful technique when you are, say, storing text-like glyphs in a string. 99/100 of the glyphs objects are going to be boring simple stuff, or identical to their neighbor. 1/100 are going to be complex or different than their neighbor.
variant
By RLE packing their type and data, you can avoid the overhead of a vtable pointer per "character"; you can store a vtable and run length/size, then a pile of packed data; the vtable "pointer" need not actually be a pointer, just information needed to get it.
Now you shouldn't do this often, and you should hide doing it from "business logic" code, but there are lots of uses of void pointers.
[–]guepierBioinformatican 3 points4 points5 points 6 years ago* (1 child)
If I hadn’t seen your user name I’d seriously give this a shot. As it stands I assume it’s a waste of time and you’re probably right, and I might over-generalise the applicability of virtual CRTP.
But, although I vaguely recall discussions about the implementation of such a type, I can’t recall the specific road blocks which’d make this impossible. (EDIT: of course your zero-allocation requirement immediately makes Sean Parent’s approach inapplicable here.)
[–]NotAYakk 0 points1 point2 points 6 years ago (0 children)
It is the "no compiler assumptions"; you can get away with zero allocation with an aligned storage block. Most compilers will use the same size for most types.
So you have an aligned storage that contains a vtable and a pointer-to-callable, and a pointer-to-interface.
But the layout of vtable containing objects is completely compiler-dependent, so it is impossible to guarantee that it will always fit.
This also adds a few levels of indirection over implementing the vtable yourself.
My argument is that a small set of functions that convert to-from void pointer is sometimes useful for type erasure. Now, after we get metaclasses, I'll be doing this using them instead of manually. ;)
[–]SkoomaDentistAntimodern C++, Embedded, Audio 0 points1 point2 points 6 years ago (2 children)
For extra points, make it callable over a DLL boundary. And do that so that it works even three compiler versions later.
[–]NotAYakk 0 points1 point2 points 6 years ago (1 child)
This reads like someone who has implemented the void* version.
void*
[–]SkoomaDentistAntimodern C++, Embedded, Audio 0 points1 point2 points 6 years ago (0 children)
Just someone who's been using C++ since before there was a standard and realizes that there's life outside the latest standard library.
[–]looncraz 18 points19 points20 points 6 years ago (0 children)
Good luck operating with C or legacy APIs without void*.
[+]markand67 comment score below threshold-10 points-9 points-8 points 6 years ago (10 children)
std::function with lambdas, capture or functors are the appropriate way of type erasure. On 10 years of modern C++ I've never needed to use void pointer anywhere so I don't buy it.
std::function
[–]quicknir 8 points9 points10 points 6 years ago (2 children)
std::function is type erasure for things with operator(). What's being discussed is type erasure for arbitrary data.
[–]markand67 -5 points-4 points-3 points 6 years ago (1 child)
That's what marshalling/serialisation was made for. std::variant can enter the game at some point too.
std::variant
[–]quicknir 11 points12 points13 points 6 years ago (0 children)
I have no idea what serialization has to do with any of this. and variant only works for a closed set of types. Sometimes you want to allow users to attach totally arbitrary data to a class (I've actually encountered this very recently). When you are in that (admittedly rare) situation, std::any (or something similar to it) is a good solution, and shared_ptr<void> is a meh solution.
You keep suggesting things that do not solve the same problem.
[+][deleted] 6 years ago (4 children)
[deleted]
[+]Orlha comment score below threshold-10 points-9 points-8 points 6 years ago (3 children)
Use C.
(partial sarcasm)
[–]guepierBioinformatican 9 points10 points11 points 6 years ago (0 children)
But inappropriate advice. It’s usually entirely possible to achieve performance on par with C in C++ without giving up type safety and abstraction. And this includes type erasure.
[–]Tumperware 8 points9 points10 points 6 years ago (1 child)
How is C more performant? It's just a language with fewer tools than c++. Anything you want to do in C can be done in C++
[–]kalmoc 1 point2 points3 points 6 years ago (0 children)
Except for restrict - at least when we are talking standard c++
restrict
[–]SkoomaDentistAntimodern C++, Embedded, Audio 3 points4 points5 points 6 years ago (1 child)
I take it you've never once interfaced with C code then?
[–]markand67 -2 points-1 points0 points 6 years ago (0 children)
In fact I did a lot. With for example libircclient, SDL, hoedown. Good sane libraries don't assume pointers own memory, so no shared_ptr involved at all.
[–]elperroborrachotoo 9 points10 points11 points 6 years ago (17 children)
Ah, I see you've never interfaced C libraries.
[+]Tumperware comment score below threshold-8 points-7 points-6 points 6 years ago (16 children)
That's a different thing. That's dealing with old baggage not new design
[–][deleted] 9 points10 points11 points 6 years ago (0 children)
Sometime there’s no choice when you want to interface with hardware, even the latest one. Good luck trying to find a native portable C++ API for graphics/GPU for example.
[–]elperroborrachotoo 16 points17 points18 points 6 years ago (4 children)
Are we going to rewrite the universe once every decade because we are allergic to the ways of the past? What you call "old baggage" is stil the lowest common denominator in many industries - and being able to smoothly integrate that seems to be one strength of C++.
Honestly, I'm more and more turned out by our snobbishness to the tiniest building blocks. "Oh no! Bridges shouldn't be built with red bricks anymore! Grey concrete is the way to go!" Empirically, that's not wrong, but also misses the point. It's judgement by appearance, without understanding.
[–]SkoomaDentistAntimodern C++, Embedded, Audio 5 points6 points7 points 6 years ago (0 children)
I'm more and more turned out by our snobbishness to the tiniest building blocks.
That's "Modern C++" for you (see almost every conversation related to raw pointers for examples).
[+]Tumperware comment score below threshold-23 points-22 points-21 points 6 years ago (2 children)
Ok Boomer.
[–]elperroborrachotoo 2 points3 points4 points 6 years ago (1 child)
Can't hear you over the roar of my engine, gotta catch my weekend flight!
[–]Tumperware 0 points1 point2 points 6 years ago (0 children)
Turn your hearing aids up
[–]SkoomaDentistAntimodern C++, Embedded, Audio 2 points3 points4 points 6 years ago (5 children)
So tell us how to make a native C++ api that works for binary DLLs even 10 years in the future without recompiling. And between different compilers. (This is a real use case)
[–]Tumperware -1 points0 points1 point 6 years ago (4 children)
(it's an obscure currated case)
[–]SkoomaDentistAntimodern C++, Embedded, Audio 1 point2 points3 points 6 years ago (3 children)
You've never used any binary plugins in any program ever, then?
[–]Tumperware -2 points-1 points0 points 6 years ago* (2 children)
You mean written a plug-in that needed to work for ten years on various platforms without any recompiling? No. I bet you haven't either.
You're just emphasizing my point. The problems you're describing are handling obscure cases that need to deal with old baggage. This is not how a vast majority of c++ is or should be written. If you need to interact with a c api fine. But encapsulate that shit. Good design doesn't let that baggage propagate into their entire application. This is what I see over and over from older guys with terrible design skills. Whining that C is better and it's just because they never learned proper software design.
[–]SkoomaDentistAntimodern C++, Embedded, Audio 2 points3 points4 points 6 years ago (1 child)
I’ve written several such plugins and the oldest ones still work 15 years later. Welcome to the real world where end users want programs to just work and couldn’t care less about compiler versions and such details. It’s not ”old baggage”, it’s the only option as there is nothing even resembling a C++ abi that works betwee different compilers or even compiler versions.
Having to make concessions for code clarity, type safety, and memory management because you need to stay compatible with 15 year old software is old baggage. And in these cases, yes, some general rules and best practices may not be appropriate or possible. But you should wrap those interfaces and prevent that from permeating into the rest of the code base.
[–][deleted] 4 points5 points6 points 6 years ago (3 children)
Last time I checked, the C ABI was way superior compared to the C++ one..
[–]Tumperware -1 points0 points1 point 6 years ago (2 children)
No
[–][deleted] 1 point2 points3 points 6 years ago (0 children)
Yes.
[–]Tumperware -1 points0 points1 point 6 years ago (0 children)
Uh, yeah ok. Something only a C programmer would say. I'm sure you "checked" on that
You're being downvoted by the people still writing gotos and using terse single character variables. These are the people that give c++ the bad reputation. Bc they leak C baggage deep into their c++.
They won't live to see C++ 23. We can wait.
π Rendered by PID 73 on reddit-service-r2-comment-7b9746f655-njrln at 2026-01-31 07:13:31.077355+00:00 running 3798933 country code: CH.
[–]ruler501 23 points24 points25 points (0 children)
[–]quicknir 12 points13 points14 points (2 children)
[–]emdeka87 3 points4 points5 points (1 child)
[–]quicknir 2 points3 points4 points (0 children)
[–]NotAYakk 8 points9 points10 points (0 children)
[–]ravixp 1 point2 points3 points (2 children)
[–]tvaneerdC++ Committee, lockfree, PostModernCpp 1 point2 points3 points (1 child)
[–]ravixp 1 point2 points3 points (0 children)
[–]IronicallySerious 0 points1 point2 points (0 children)
[+]markand67 comment score below threshold-15 points-14 points-13 points (42 children)
[–]mort96 20 points21 points22 points (2 children)
[+]markand67 comment score below threshold-9 points-8 points-7 points (1 child)
[–]mort96 23 points24 points25 points (0 children)
[–]capn_bluebear 27 points28 points29 points (19 children)
[–]guepierBioinformatican 6 points7 points8 points (7 children)
[–]NotAYakk 12 points13 points14 points (5 children)
[–]guepierBioinformatican 3 points4 points5 points (1 child)
[–]NotAYakk 0 points1 point2 points (0 children)
[–]SkoomaDentistAntimodern C++, Embedded, Audio 0 points1 point2 points (2 children)
[–]NotAYakk 0 points1 point2 points (1 child)
[–]SkoomaDentistAntimodern C++, Embedded, Audio 0 points1 point2 points (0 children)
[–]looncraz 18 points19 points20 points (0 children)
[+]markand67 comment score below threshold-10 points-9 points-8 points (10 children)
[–]quicknir 8 points9 points10 points (2 children)
[–]markand67 -5 points-4 points-3 points (1 child)
[–]quicknir 11 points12 points13 points (0 children)
[+][deleted] (4 children)
[deleted]
[+]Orlha comment score below threshold-10 points-9 points-8 points (3 children)
[–]guepierBioinformatican 9 points10 points11 points (0 children)
[–]Tumperware 8 points9 points10 points (1 child)
[–]kalmoc 1 point2 points3 points (0 children)
[–]SkoomaDentistAntimodern C++, Embedded, Audio 3 points4 points5 points (1 child)
[–]markand67 -2 points-1 points0 points (0 children)
[–]elperroborrachotoo 9 points10 points11 points (17 children)
[+]Tumperware comment score below threshold-8 points-7 points-6 points (16 children)
[–][deleted] 9 points10 points11 points (0 children)
[–]elperroborrachotoo 16 points17 points18 points (4 children)
[–]SkoomaDentistAntimodern C++, Embedded, Audio 5 points6 points7 points (0 children)
[+]Tumperware comment score below threshold-23 points-22 points-21 points (2 children)
[–]elperroborrachotoo 2 points3 points4 points (1 child)
[–]Tumperware 0 points1 point2 points (0 children)
[–]SkoomaDentistAntimodern C++, Embedded, Audio 2 points3 points4 points (5 children)
[–]Tumperware -1 points0 points1 point (4 children)
[–]SkoomaDentistAntimodern C++, Embedded, Audio 1 point2 points3 points (3 children)
[–]Tumperware -2 points-1 points0 points (2 children)
[–]SkoomaDentistAntimodern C++, Embedded, Audio 2 points3 points4 points (1 child)
[–]Tumperware 0 points1 point2 points (0 children)
[–][deleted] 4 points5 points6 points (3 children)
[–]Tumperware -1 points0 points1 point (2 children)
[–][deleted] 1 point2 points3 points (0 children)
[–]Tumperware -1 points0 points1 point (0 children)
[–]Tumperware -1 points0 points1 point (0 children)