20 comments

[ 44.5 ms ] story [ 476 ms ] thread
I'm more interested in "C++ Templates in Less Than 3 Years".
Spend two years in haskel, c++ templates will only take you 6 months: net savings 6 months.

Seriously, once you are good at functional programming (which haskel will give you) C++ templates are just a syntax problem: you should be able to learn that awful syntax in 6 months once you don't have the overhead of trying to learn functional programming at the same time.

The guidelines say to use class when there is an invariant and struct otherwise. This is counter productive because if a struct without invariants suddenly gains an invariant, it should be changed to class. Which doesn't matter except that all forward declarations now also must change (despite years of more permissive compilers allowing a forward declaration of a class later defined as a struct, this is not standard).

Better to always use struct and never class, or the opposite. Always class is simpler because the first members declared in most classes are public, and struct saves you typing "public:" at the top of every class. But always class has the advantage that it is far more popular in C++ library code...including std::array which has no invariants.

I can't think of a case where that's not just a quick find/replace to fix. Or, if you're using a more modern IDE, a refactoring rule.

Do you have something in mind that might be more complicated?

I write a library that is used by many downstream projects. If I make the struct->class change in my code all my users who have predeclared my class have to fix their code. They probably won't read release notes, and might be using a permissive compiler (gcc is, clang is not - at least in my experience) so it can be a long time before they get weird bugs reports, which take them time to understand.
That’s one of the reasons why “forward headers” are a much better pattern than manually declaring things everywhere. One person saying “struct X;” and another saying “class X;” is a compiler error when the inconsistency is found, and it gets worse when namespaces change, etc. Just push the maintainer to handle this (e.g. <iosfwd>).
If the best example is interfaces, why not just add interfaces, instead of having every library contain its own slightly incompatible implementation of them?
A much more interesting example is the replacing of Qt or Windows's meta-object compilers with purely in-language features and without resorting to macros.
The ship has probably sailed but had C++ had reflection back when, maybe the whole Qt paradigm could do without MOCs. I feel that with C++ we have backed ourselves into a complexity corner and now building more stuff to get out of it while retaining old habits.
That is best only in the context of easy to explain and understand. As soon as I saw the proposal I thought of 3 different uses for this that are very specific to my domain. None of them are easy to explain unless you know our implementation (which I of course cannot talk about publicly)

As the other poster said, qt moc is another example of where meta classes can make things easier, but explaining how it works would take much more code with no other benefit.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p093... says "C++ is complicated, too complicated, yet we cannot remove significant facilities and changing them is very hard. Changing parts deemed insignificant can be risky (we need better analysis tools [Winter,2016]) and the potential gains would be insignificant. However, we badly need to simplify use of C++" in its long-term goals. However, almost every short- and medium-term change planned runs counter to that long-term goal. How are we supposed to reach a long-term goal if every step taken along the way is in the opposite direction?
Its almost like a description of a bad codebase. The parallels are quite interesting.
Maybe a version of C++ that breaks backwards compatibility? The assumption is that it will only be used for new projects?
That is really the best solution, especially since it’s easier than ever to partition code bases (e.g. multi-process tools where you’ve only had time to modernize one of the pieces so far). It’s no longer “new project” so much as “new piece”.
There are such things, for instance D is a "better" C++, but isn't widely used. By doing a cleanup of a language you throw away libraries, knowledge, tools, ... See also the missing success of Perl 6.
> However, almost every short- and medium-term change planned runs counter to that long-term goal.

I'm not sure the C++ commitee would agree with you. Every change adds to the language and hence, in a certain sense, makes things more complex, yes. But the idea is to add simpler alternatives to some current terrible stuff.

As for metaclasses, they enable to define some fairly clean "class contracts", i.e. it constraints how some class can be implemented - and will report a clean error message at compile-time if the constraints are breached. Contrast to the current situation where failing to respect such a contract will make your program blow up at runtime or generate a byzantine template error at compile-time.

I remember beginning to learn C++ as a teenage game modder and loving it, but now that I'm older and have been exposed to the other facets of the language, my appreciation for plain old ANSI C and its interop has grown beyond my love for the former. There's just too much shit going on in C++. It's an example of a language where not enough people said "no".

You can always add, but it's so very difficult to take away.

I just use struct because access defaults to public. Inheritance is almost always public, and I prefer to declare public members at the top of my class for readability. I don't see any profound lessons of software engineering arising from the C++ definitions of class and struct. I don't read class and struct as having strong semantic conventions communicating intent. I don't see a significant problem with the way we currently define interfaces using them.

I'm sure I'm just used to things the way they are, but this does not seem to me like a strongly motivating example for metaclasses.