News for hackers. Stuff that matters.
Re:Goals and Priorities for C++ by gumby on Friday May 22, 2020 @02:07AM (#23269107)
This did notrequire multiple inheritance.* It is for the serialization system for a complex semantic graph library. The library itself did no I/O. That was fine for writing various UIs and programs that used the library. But how to save and restore the graphs? They included a bunch of statistical and bookkeeping data not exposed in the UI.

I wrote a “serializer/deserializer” package that did t actually save anything but could represent the data and swizzle it so the in-memory structures could use raw pointers. This could be validated as correct in CI.

Then in a separate I/O library I wrote a module that could generate JSON and store it in a file, using specializations of these virtual baseclasses. When the underlying library changed representation client code didn’t have to written.

My JSON thing was too slow so someone wrote one that backed into a SQL database. A lot faster, though versioning went out the window. Anyway someone could write a fast binary format if that matters and they should all continue to work.

* I mostly gave up on MI in the mid 80s when it was clear it made encapsulation harder to understand (and this was in a language with explicit method combinators too). However I still find mixin classes quite valuable, though again not in widespread use.

Re:Goals and Priorities for C++ by mehrdadn on Friday May 22, 2020 @02:23AM (#23269189)
Oh wow. So it sounds like what you got out of virtual inheritance here is avoiding some kind of ABI breakage? That's interesting, I've never come across this use case before, but I'll be thinking more about it and looking out for it in the future. Thanks!
Re:Goals and Priorities for C++ by gumby on Friday May 22, 2020 @03:29AM (#23269531)
No, it was about encapsulation. Consider the save dialogue: if wants to have an array of the json saver, sql saver etc and perhaps display them in a pull down list. Virtual inheritance let’s you make the std::vector of the base class. Otherwise what could you use? A pointer, and manypually reimplement the vtable?

Also this means changes to the underlying representation don’t always require changes to the dependent classes, which I suppose you could consider an ABI change.

Maybe an easier way to characterize it is to consider the virtual classes a way to implement plug ins.

Re:Goals and Priorities for C++ by maxlybbert on Friday May 22, 2020 @09:51AM (#23272034)
One annoying thing about C++ is that certain terms and keywords are overloaded. So, while having virtual functions in a base class is a very common design approach, it isn’t “virtual inheritance” ( https://en.wikipedia.org/wiki/Virtual_inheritance ).

Many people consider virtual inheritance a complexity of the language. Why is it possible for a class to inherit from a base class multiple times through multiple paths (the standard case) or to have the compiler coalesce those paths so that the child class only inherits once from the parent/grandparent? The thing is, once you have multiple inheritance, somebody is going to try to inherit from the same base class multiple times. The language can either support it or declare it an error. It’s not clear to me why it’s wrong to for the language to allow it, even though everywhere I’ve worked with a C++ coding standard has said “if your design requires virtual inheritance, discuss your design with other experienced programmers to see if that can be changed.”

Re:Goals and Priorities for C++ by gumby on Friday May 22, 2020 @12:13PM (#23273641)
> One annoying thing about C++ is that certain terms and keywords are overloaded.

It's a no-win choice, though I agree C++ chose the wrong path: trying as much as possible to avoid adding new keywords. It leads to the problem you describe, as well as some confusion in this very thread (which could be my fault, but honestly I don't know -- that's the problem!).

The committee seems to have moved away from this over the years which has lead to complaints of too many keywords and identifiers. Which is why I call it no win.

The function virtual specifier in the base clause is reasonable: if you store something into parent_class.instannce_var and there are two copies of parent_class in your structure which one is stored to and is the choice consistent in all compilation units? This specifier guarantees that the answer is "yes". I don't know why it isn't the default though.

More generally, back in the day I used to use a bunch of different method combinators with flavors (later CLOS). Apart from the useful :before and :after, they generally lead to undebuggable code.

Re:Goals and Priorities for C++ by maxlybbert on Friday May 22, 2020 @01:35PM (#23274730)
I understand why they try to reuse keywords and symbols, and why they intentionally pick really ugly keywords when they add new ones. I can’t say they’re wrong, but I still find it annoying.
Re:Goals and Priorities for C++ by gray_-_wolf on Sunday May 24, 2020 @05:40AM (#23290382)
They could just go the C-way and introduce new keywords in reserved namespace (`_Static_assert`) and provide opt-in header to make them less ugly (`assert.h` and `static_assert` macro).
Re:Goals and Priorities for C++ by mehrdadn on Friday May 22, 2020 @03:35AM (#23269564)
Okay then I'm lost. Why can't you have JsonSaver, SqlSaver, etc. inherit from a Saver class the normal way, and store instances of them in a std::vector<std::unique_ptr<Saver>>? Then you'd just need struct Saver { virtual ~Saver() { } virtual void save(...) { ... } } along with struct JsonSaver : Saver { void save(...) override { ... } } and it should work, right? I'm confused why you need a virtual base class on top of that. Are you by any chance confusing "base classes with virtual methods" with "virtual base classes" (which may or may not contain virtual methods)?
Re:Goals and Priorities for C++ by gumby on Friday May 22, 2020 @12:02PM (#23273502)
Yes, I mean literally base classes with vtables not the "virtual" specifier of a superclass ("base class" in C++). Apologies for the confusion!

I do think it's a useful feature, except as I think most people finally agree, MI is more often than not a cause for confusion.

It's funny that of all the different method combinators (another source of confusion) only that one was chosen.

BTW I don't think a unique_ptr is needed in the case I described.