Live data from Hacker News

Implementing a class with void*

web.eecs.utk.edu

21–30 of 78 posts

Re: Implementing a class with void*

#21
post #17

Earlier quoted context omitted.

> and maybe more surprisingly, add/removing virtual functions I don't have the spec handy but fairly certain that v-table implementation is compiler specific and while it may work it isn't guaranteed. However if you declare the function symbols as dynamic then you can leverage the linker to dynamically resolve the right symbols with the matching opaque data and achieve binary compatibility(assuming you use the same c…

vtable layout is defined by the ABI, which is (mostly) consistent across major compilers everywhere except MSVC, however if MSVC ever broke vtable layout then everything that relies on COM would break on Windows. Which is basically all of Windows user space.

[deleted]

Re: Implementing a class with void*

#22
post #4

I'm surprised he doesn't refer to it by name (Pimpl). In C++ it has the advantage that you can change your implementation and retain binary compatibility because the size of your class doesn't change as you add/remove member variables (and maybe more surprisingly, add/removing virtual functions). If you're going to use C++, seems like it would be better to avoid the void* by class C { protected: struct Impl; std::uni…

The downside of unique_ptr used this way is that you have to define ~C in the same translation unit that the declaration of C::Impl lives.

No it isn't. What is a downside is you could not be arsed to explain why (blah means blah) to a reasonably intelligent audience.

Re: Implementing a class with void*

#23
I haven't thought about him in years, but James Plank is the reason I'm a programmer today. I was a terrible student and he likely doesn't remember me, but his classes were too much fun. He just assigned projects and a timeline and live coded similar exercises in class mostly along with the timeline. I probably would have switched away from Computer Engineering (a degree I barely use) without his classes.

Re: Implementing a class with void*

#25
post #4

I'm surprised he doesn't refer to it by name (Pimpl). In C++ it has the advantage that you can change your implementation and retain binary compatibility because the size of your class doesn't change as you add/remove member variables (and maybe more surprisingly, add/removing virtual functions). If you're going to use C++, seems like it would be better to avoid the void* by class C { protected: struct Impl; std::uni…

The downside of unique_ptr used this way is that you have to define ~C in the same translation unit that the declaration of C::Impl lives.

You can use a custom deleter, e.g.

    struct deleter_t { void operator()(impl_t *); };
    using impl_unique_ptr_t = std::unique_ptr;

You can place the implementation of the deleter alongside the impl.

Re: Implementing a class with void*

#26
post #9

Back in the 1990s, the video game company I worked at would hang a couple of extra void pointers in every class just to, you know, store extra things that are needed as time goes on…

This was common in the 90s, BeOS had these everywhere in its API classes

This is because of the fragile ABI problem in C++--it's not good for APIs for this reason. I used to program for the macOS kernel and they (used to) do exactly the same thing.

See `OSMetaClassDefineReservedUnused` in `OSObject.cpp`, here: https://github.com/apple/darwin-xnu/blob/main/libkern/c++/OS...

Re: Implementing a class with void*

#27

This is a well-known way to achieve separation of definition and implementation. The disadvantage of the method proposed in the article is that, now everything needs a pointer indirection. A solution that fixes the drawback is used by lz4's library implementation: instead of storing a void star, store a char[] array of same size as the real struct. (of course, now you have to manually make sure the struct size are in…

Why not `typedef struct state state_t` in the header file, then have a `state_t state` in the header file with the `struct state { ... }` definition in the source file? This is similar to what I do in C, I don't see why it wouldn't work in C++.

That would fix the type safety issue of using a void* but not the extra pointer indirection issue, since your state struct would still have to be a pointer if you want the declaration outside of the header.

Re: Implementing a class with void*

#28
post #18

Earlier quoted context omitted.

Or don't do that (the char array trick) in C++ because implementers and standardizers are not clear about when/if you are allowed to store other objects in an array of chars, and even if you are it is tricky because you need to manually manage the alignment, or they are attempting to replace char with std::byte in the long term but don't really have a comprehensive and detailed plan to do so, etc. The implementation…

Yes, strict aliasing (or type-based alias analysis?) is quite crazy, and there are some murky dark corners where the specification is different between C and C++.. I think they have a std::launder thing exactly for this purpose of "safely casting an array of bytes into an object". However, in this particular case (of using char array to hide real implementation), the implementation resides in another translation unit…

For projects of mixed quality without basically an unbounded workforce maintaining them (who could investigate rare/arcane bugs "introduced" by the "optimizers" in some builds), and/or using "tricks", I too am fond of not using LTO.

But then I force myself to find a second reason for why the program will run correctly, and unfortunately nowadays it is more and more being strictly-conforming. Relearning std::launder, TBAA, pointer provenance, etc. every time is way too consuming. I'm forced to give-up on programmer optimization and hope for the compiler to be really up to its mythical promises (and this yet: without LTO; too dangerous...)

Re: Implementing a class with void*

#29
post #4

I'm surprised he doesn't refer to it by name (Pimpl). In C++ it has the advantage that you can change your implementation and retain binary compatibility because the size of your class doesn't change as you add/remove member variables (and maybe more surprisingly, add/removing virtual functions). If you're going to use C++, seems like it would be better to avoid the void* by class C { protected: struct Impl; std::uni…

Came here to say exactly that. You can also do this, thought it looks a little worse it allows for even more flexibility, such as complete decoupling of Impl from A across different files: // Forward declaration of Impl. What does Impl do? // You're not allowed to know. class Impl; class A { protected: Impl* mImpl; }; I've been using this trick but for a different reason - to reduce the number of #include statements…

Between this trick and generous use of forward declarations, I was able to remove almost all "headers included from headers" from a past project of mine, speeding up compilation by probably 3X (never measured it but it was observably faster). Maybe today's compilers optimize all these includes away and it doesn't make a difference anymore but it used to.

These are the kinds of refactorings you often need to justify with hours of arguments and approvals and religious fights and code reviews at work, but can do in an afternoon in a private project just because it makes the code nicer.

Re: Implementing a class with void*

#30
post #4

I'm surprised he doesn't refer to it by name (Pimpl). In C++ it has the advantage that you can change your implementation and retain binary compatibility because the size of your class doesn't change as you add/remove member variables (and maybe more surprisingly, add/removing virtual functions). If you're going to use C++, seems like it would be better to avoid the void* by class C { protected: struct Impl; std::uni…

> ...you can change your implementation and retain binary compatibility...

Maybe? I can still think of ways to have ABI problems in the implementation of class C.

It's true that there are fewer ABI problems to worry about, though.

Post reply on HN