This strikes me as throwing the baby out with the bathwater. While the criticisms are valid, and people love to hate C++ for all sorts of reasons (I avoid C++ exceptions altogether), C++ is for practical purposes a superset of C, so if a C idiom works better than its C++ equivalent, you can just use it instead. I've been working on a project which has necessarily been written mostly in pure C (kernel code), and I do really miss C++'s extra type safety. (GCC has some type warnings that help, but it's still not as safe)
Then again, maybe an entirely different language, geared towards high availability, such as Erlang or Ada, might have been a better choice in the author's case.
Just because C++ is a superset of C doesn't make it strictly better. The presence of additional features can be a liability. The obvious problem is that if you want to use the C subset in a multi-person project (whose team evolves over time), you have to create a way to enforce that. Another example is that it's more difficult to produce static analysis tools like lint. (As an example, lint in C detects unused stack variables. This is trivial for C. This is extremely difficult for C++ because the mere construction of the object on the stack often has important side effects.)
It's not even a superset. While not as bad as Netscape changing LiveScript to JavaScript to market off of Java, "C++ is a superset of C!" is still a marketing gimmick. At least with C++11 everyone I've heard talk of it agrees it's a different language now, maybe people will stop bundling "C/C++" on the resume together. For anyone curious about a few other trivial problems of C and C++ incompatibility, check out http://yosefk.com/c++fqa/picture.html#fqa-6.11 (The full FQA there is quite good, being based off correcting/questioning the frequently cited C++ FAQ, so if you want to actually learn C++ more than it probably deserves the FQA will help you along the way. The full section on mixing C and C++ is here: http://yosefk.com/c++fqa/mixing.html )
What you describe as a marketing gimmick has let us gradually migrate a 10M line cross-platform C codebase to C++. There are plenty of reasons to dislike C++ but casually disparaging them often means you miss reasons for its continued real-world success.
While it isn't a strict superset, there aren't any C features you can't use in C++, unless you count lack of pointer type safety as a feature. This was the original point I was making (and note how I didn't say it was an actual superset).
The two ways (C90 and C99) you can create a variable length item at the end of a structure in C are invalid C++. You can't express them at all.
I work around it by making a one element array and using "sizeof(MyThing) - 1" everywhere when I want to reference the size then use placement new and the ::new operator to do the allocation and initialization of my object.
It works, but it's not very straightforward.
In general, I rather like C++, but it does make a few things harder than C.
Yes -- see my post above. Syntax and semantics simple enough to be easily statically analyzed (both by humans and tools like lint) are a language feature that C has over C++.
More generally, many people see significant value in the very property of C that it doesn't let you do things that C++ lets you do. That's why the argument that "C++ is a superset" and "there's no good reason not to simply use a C++ compiler on your C code" is bogus.
The thing is, if you use the subset of C++ people usually recommend, you're hardly better off than with C. Turning off exceptions means you can't use the STL (alloc errors throw) and you can't do any non-trivial work in your constructor so you have to manually initialize everything anyway.
Not true. Many STL distributions have a compile-time flag you can set to disable all exceptions. Otherwise, there are entire STL distributions you can compile against that are exception free.
I wouldn't go so far as to actually turn of exceptions at the compiler level. I just see no need to use them in my own code. And as for failing STL allocations: a lot of the time you realistically can't recover anyway, and where you can and want to, well, you'll have to suck it up and put a try/catch block in there. The world isn't going to suddenly end.
In C++, allocation errors don't need to throw an exception.
Object* obj = new (nothrow) Object;
If the above allocation fails, obj will have the value NULL. It's tedious, but you could replace the default, throwing allocation with a non-throwing allocation in all places of the STL. However, various parts of the STL throw other kinds of exceptions. But, I think one could have a compromise, where you deal with exceptions from libraries you use, but you don't throw any yourself, instead using C-style error handling.
If you replace the STL allocator with a non-throwing allocator how do you know that that vector you just push_back'd didn't actually allocate any new memory?
Indeed, you have to roll your own data structures. This is pretty common in the game development world, where exceptions are considered to have unpredictable performance characteristics.
That is a pretty tight requirement, considering the internals of Ogre 3D engine. It is full with exception classes (some might argue it is way too overengineered.)
Are custom data structures available as open source that don't use exceptions? Or perhaps can you please name an engine that already has this?
Valve's Source SDK makes extensive use of their own data structures, however it is very specialized. For example, linked lists are allocated as growing, contiguous blocks of memory to reduce cache misses. The Doom3 source code might be worth looking at, but I'm sure it's the same story. https://github.com/TTimo/doom3.gpl
At the very least, there's a lot of great reference out there.
Which usually aren't really recoverable anyway. I mean, you can also blow the stack. Then what? Just ignore those essentially unrecoverable eventualities and terminate.
Many would say doing non trivial work in the constructor is bad practice anyway. Constructors should be simple, set instance vars, and be done; all necessary state should be passed in. The objects job is to be what it is, not be its own factory. Construction of complex objects is better left to factory methods, factories, or builders.
Part of the reason I dislike C++ is that I learned Borland's Object Pascal first. Knowing something else that did the same things as C++, only in a less cluttered way, was a disappointment.
Also, back in 1990, there was arguably no standard, widely distributed, C++ library, either. (which also made Object Pascal more appealing, if you didn't mind getting a language from one vendor that only ran on DOS or Windows)
C is a quite acceptable portable assembler, though :-)
Don't get me wrong, I'd love to see a real contender for a C++ replacement. I just don't understand the attitude that because some aspect of C++ is distasteful, going back to pure C is the answer.
Then again, maybe an entirely different language, geared towards high availability, such as Erlang or Ada, might have been a better choice in the author's case.
I don't follow, but it's clear from your other comments that you know what you're talking about, so I fear I'm missing something.
His goal is for ZeroMQ/Crossroads to be part of the infrastructure, one of those reliable "3rd party libraries" he wants to avoid using himself. He wants it to be a rock solid base on which a high availability solution can be built. Likely this solution will be built in some higher level language (Perl, Python, Ruby, Java, Erlang), and he wants to insure that that language doesn't get tripped up by error handling in the his library.
My instinct is that you need to write the library in something that compiles to a shared library with a C ABI, since this is the only common denominator which the higher level languages can link to. While this is technically possible with Ada, I don't know of any common libraries that do it. And I can't see how it would work for Erlang. I think the only realistic choices are C and a subset C++ with "extern C". Maybe also Go? Do Ada and Erlang fit the bill for this in a way that I don't understand?
I love Go and Go makes it pretty easy to wrap C (and thus strengthens the argument for using C as a basis for any core libraries), but the story for consuming Go code from anything other than Go is basically non-existent right now. There isn't even a defined way to make Go shared libraries that other Go code can access yet.
This ^
If a language feature doesn't work for you, you don't need to use it. In this case not using it is writing c, but this is true to every program language.
When I use a oo language I always use composition and ignore inheritance.
Unfortunately you can't avoid dealing with those complexities if you use a library, but if the advantages of using a language/platform outweighs the advantages, is awlays possible to work around it.
But that's not true. Giving up on exception handling and initialization code in constructors still leaves tons of super useful C++ to use. Generic programming, the standard library, what's left of OOP rather than crazy function pointer stuff, etc.
This obviously depends on your environment. I don't recommend doing this in embedded devices or an OS kernel (this is probably why even C++ OS kernels have exceptions disabled, and no STL implementation).
But if you're just an app running in an operating system with virtual memory, the kernel's out-of-memory-killer can take you out anytime anyway, so trying to recover from every single failed memory allocation is often futile. The most likely reason to get a failed memory allocation on such a system is that you're out of address space (in 32-bit environments). If this is an issue for your app, you'll need to take higher level design decisions to cope with this fact anyway.
If you actually run out of memory (physical + swap) on such a system, you will usually not find out on allocation. Instead, allocations (mmap()/sbrk()) will succeed, but when you write to a previously untouched memory page, it will page fault, not find a backing store for it, and invoke the out-of-memory-killer. Good luck recovering from that.
Just to be clear, this doesn't absolve you from managing and conserving your memory diligently. It's just that if you wait for memory allocations to fail before reining in your program, you've probably made your user's system swap so badly it's barely usable. No cookie for you!
If the system is out of memory, and you're not in some special case huge allocation, odds are very high your program can't proceed in any useful way. You're going to have to terminate anyway. Why pretend it's a recoverable exception? It's usually of the same class as a stack overflow.
If you can't tolerate that philosophy, you might as well just give up dynamic allocation altogether and have everything in stack allocated std::array's. But you still might blow the stack.
What I meant by "not using it is writing c" is that in this case you can put it as "c vs c++", but the real issue is using or not using a language feature. I phrased it badly.
Part of the issue with doing that is that by compiling as C++ the symbols get mangled in a different manner and can lead to areas where you have to compile nearly everything as C++. Or you have to make sure that everything that you might want to face the outside world is marked with extern "C" {}.
and mark any C-callable functions with it. Easy. The real linkage problems you'll run into with C++ are in dynamic libraries. The higher level of abstraction hides some problems that are really obvious at the C level. Fortunately, you only need to care about this if you need to support third-party plugins to your software. If that's the case, you may want to reconsider your choice of using a low-level language such as C++ or C.
This is pretty much the way I use C++; as C, except with the occasional excursion into C++ when it's more convenient.
The downside is that while I claim to be able to program in C++, my C++ idiom has nothing in common with anyone else's. For example: what the hell is an STL? How do exceptions work? I have no clue.
Practical use of the STL can be learned in an afternoon. Just focus on the Big Four: string, map, vector, and unordered_map (last one is in in c++11 only).
I think it's probably worth knowing the language and at least trying out all of it. Holding an opinion from an ignorant position is just blind dogma. Who knows, you might discover a delightfully useful facet.
Yeah, just don't use virtual methods or constructors on classes and his second complaint pretty much goes away. And you get a syntax and amenities that are still way nicer than C.
Then again, maybe an entirely different language, geared towards high availability, such as Erlang or Ada, might have been a better choice in the author's case.