Hacker News new | past | comments | ask | show | jobs | submit login
C++11 FQA anyone? (yosefk.com)
105 points by signa11 on Aug 27, 2014 | hide | past | favorite | 87 comments



This is a very interesting read but it's full of FUD.

You'd expect `==` to work in PHP because it compares value. With a char* reference the syntax and everything around it indicates that you're working with well... pointers (and you shouldn't be having char pointers for strings anyway). Don't even mention PHP references etc.

C++ still has a lot of going for it - no one thinks it's terribly great and awesome - but the reason people ridicule PHP and admire C++ is that it solves a much bigger problem.

- In PHP you don't have resource management, the process kind of just dies and resources get deallocated. In C++ that's not acceptable for perfomance. - In PHP you have memory safety - oh wait you really don't, if you do silly things like use raw references you can still get screwed.. experienced C++ programmers don't fall to that pit either. - In PHP you don't have to explicitly deal with memory which is again because you're solving a much easier problem. When your whole world is an immutable page request response cycle life is rainbows and sunshine.

Comparing languages is always ridiculous and populistic but that comparison was just bonkers. Not that C++ doesn't have quirks - it sure does, but comparing it to PHP is just silly.

(Not saying anything about PHP being a bad or good language here, just that the comparison is ridiculous)


FTFA:

    I have observed someone do this: _myarr[5]={0}; – they had in the
    .h file the definition int _myarr[5] and they remembered that this
    thing could be initialized with {0} in other contexts. What they
    did wouldn't compile in C++98; in C++11 it promptly assigned the
    int 0 to the non-existent 5th element of _myarr, and the usual
    hilarity ensued. Imagine how PHP would be ridiculed for this kind
    of little behavior – and PHP at least would never overwrite an
    unrelated variable with garbage. Imagine how with C++, the poor
    programmer will be ridiculed instead.
Let me repeat that one more time,

    the poor programmer will be ridiculed instead.
From your response,

    (and you shouldn't be having char pointers for strings anyway)

     [...]

    experienced C++ programmers don't fall to that pit either
This is what the article is about, about what you are doing again. C++ is weird, it has a bunch of unusual behaviours, and when pointed, people who fall into those traps are the ones ridiculed, instead of the language.

I don't know if C++ could have been made less weird with the constraints that it had, as others have pointed out in this thread (C compatibility with no overhead). Perhaps it couldn't be. But this article is unhappy with the attitude of defending C++'s weirdness and then blaming the programmers for falling victims to this weirdness.


"Blame" is too strong of a word, but the basic idea is that C++ provides a lot of power that PHP doesn't provide, and the price for that power is complexity. So while both languages are full of dark little corners waiting to kill you, C++'s dark little corners are there because really smart people couldn't figure out how to avoid them in all cases while still keeping the mandated design requirements, and PHP's dark little corners appear to be there because no one bothered to think anything through before banging out an interpreter.

This isn't to say C++ is the best it could be. There are plenty of outright mistakes. But on the whole, C++ is weird and complicated because it had to be, at least to a much greater degree than PHP.


If you don't know even the most basic concepts of a language like using strings for strings that's a problem in every language. You can use an array of chars in PHP and access it by a reference and then compare pointers if you _really_ want to but you don't see people ranting on that.


In C++, the following:

  "Hello, World!"
…is a null terminated array of chars. When literal strings are not, in fact, strings, this is a problem with the language. It's confusing, you see? Underlying semantics nonwithstanding, how on Earth the followig works:

   (std::string)"foo" == "foo"
and the following may not?!

   "foo" == "foo"
These are not basic concepts. These are trivia. I know there are reasons for these confusing rules, but they're still confusing. You should not mock the programmer for forgetting them now and then.


Every language has quirks and issues - if you use raw char arrays like that in general purpose C++ without an extremely good reason that's not just forgetting and trivia that's a cultural issue.

Just like you wouldn't see Python code relying on mutable default values or JavaScript value relying on `with` semantics or Java code relying on `URL` comparison through DNS very often - you shouldn't find code that relies on `"foo" == "foo"`.

I'm sorry if my comments are harsh but I really do believe C++'s issues are mostly cultural.


So, accept the traps of the language as a fact of life, and just avoid them? No, that doesn't fly with me. Programming languages aren't Forces of Nature, they are human artefacts. They can be corrected.

Of course you should never rely on `"foo" == "foo"` and other such things. Still, one would expect literal strings in the language to be of the preferred string type. C++ is the only language I know of that breaks this expectation. It does not follow the principle of least astonishment. That, is not a cultural issue.

That said, I'm willing to accept that C++ do have cultural issues. Could you tell me what they are?


It isn't so much that you ridicule the programmer; it's a question of telling the programmer "don't use these things that you see mentioned in old books, we have replacements for them now."

So, yes, comparing char*s is very different than calling strcmp; and if you want to use "==" to compare strings (so you don't have to remember to call strcmp), then use std::string.


That isn't weird. At all. The language did precisely what the programmer asked it to. When you make a language operate closely to the metal, you can expect the syntax to be more abstruse. If this kind of mistake was possible in a higher level language, I would expect that to be a language pitfall.


"When you make a language operate closely to the metal, you can expect the syntax to be more abstruse"

It's the exact opposite. Close-to-the-metal, the syntax is actually very friendly - you've got values, and you can bash them in like a half-dozen ways. C is incredibly simple (I suppose their pointer syntax is a little janky, but one can always express it "one level at a time" via typedefs).

The really complicated parts come from making high-level operations seem "easy". There is no close-to-the-metal notion of char* vs a string, or a lvalue vs an rvalue, let alone template metaprogramming.


What I should have said was provide high level abstractions while still allowing low level operations. There is an impedance mismatch that the language needs to address. Languages like Rust can get away with this by not allowing the most low level operations that are deemed unsafe and so have a more user friendly api. C on the other hand, makes no attempts at make the abstraction so the syntax is just small by definition.


You really don't think that the semantics of foo[5] = {0} vs int foo[5] = {0} being completely different in C++11 is weird?


They read differently so why shouldn't they be different? One has a type specification so reads like a declaration. The other doesn't. This wasn't weird before C++11 too. The only difference is that one didn't compile before (prior to the introduction of initializer lists).


Wow, C++ apologists really are persistent.


> if you do silly things like use raw references you can still get screwed.. experienced C++ programmers don't fall to that pit either

Yes, they do. Empirically.


It was just an example. You're completely doing the double standard thing the OP is going on about. PHP and C++ are very comparable in how much they nearly encourage programmer mistakes, yet somehow in PHP it's the language's fault, and in C++ the programmer's just an idiot.


The tough one in C++'s case is that it isn't as easy as you think to critique the choices that were made. In most cases they are consequences of following design principles (and ones that seem good) through to the end (and you may disagree with the design principles, but then you probably shouldn't use the language). With PHP, that isn't the case and Rasmus would be the first person to tell you that.


> - In PHP you don't have resource management, the process kind of just dies and resources get deallocated.

We have long running PHP processes for months at a time (hey, code reuse) and they do not suffer memory leaks. Works great actually!

However, for desktop applications and short-lived processes, freeing app-level resources is pointless and only bad for performance. Why bother running through a destructor chain when you can keep your external data clean and just kill -9 the process? This is how iOS makes you work anyway.


> Why bother running through a destructor chain ...

The Gold linker (written in C++) doesn't ( http://www.airs.com/blog/archives/362 ): "[I]n the gold linker I often deliberately omitted destructors, because many of the data structures live for the life the program; in such a case, destructors serve only to slow down program exit."

However, there are some things that you really want to know happened when the process exits for any reason. If possible, you'd probably like your files closed in a way that allows them to be re-opened. That's easy to do with destructors. Destructors: they were always for more than just memory management.


> If possible, you'd probably like your files closed in a way that allows them to be re-opened. That's easy to do with destructors.

That doesn't help with data corruption coming from the environment. The power going off on your machine, your external drive, a crash in your process or an external signal all won't give you time to exit.

There are libraries worth relying on for this, like SQLite. It's not in C++.


This is a weird argument: "I just bought a Porsche, and it handles better than any car I've owned!"/"you can't tow things with a Porsche."

Anyhow, as you implicitly acknowledge, destructors help with orderly shutdown, even if the shutdown is caused by an error condition. I prefer them to try...finally that other languages rely on. I can live with C#'s IDisposable, but I personally have a better chance of getting my destructors right than implementing IDisposable correctly (remember, in a garbage collected language, you don't have a defined order that things will be destroyed in).

But, on the completely different topic of how to do disaster recovery when both your program and the host operating system are shut down in a non-orderly manner: I personally am not aware of any language features in any language that make that easier. However, I know it can be done in C++ (stasis ( http://stasis.io/ ), SQL Server, MySQL/MariaDB, Firebird ( http://firebirdsql.org/ ) and SciDB ( http://www.scidb.org/ ) are all implemented in C++, although they aren't all necessarily object oriented C++).


Also, PHP doesn't give you type safety. I have no idea why the article said that but that's just ridiculous.


The PHP runtime does know the types of all values at all times, though, in a way that the C++ runtime, insofar as it can be said to have one, does not. To call that type _safety_ is a little much even by the standards of dynamic languages, because PHP is so willing to do implicit type coercion, but _at runtime_ a PHP program is certainly more able to detect type errors than a C++ program.


Comparing PHP with C++ is just silly in the first place. Nobody is trying to seriously write a deferred renderer that can do global illumination in PHP.


Well, he describes the FQA as "an overly combative reply to Marshall Cline's fairly combative FAQ". He's not claiming impartiality.

But yes, it does look like he's gone very far out of his way to try to find things to complain about.


After reading this I recommend people go watch this recent interview with Bjarne[0] for some insight on the compromises taken by C++, a spot of history with regard to its development in tandem with C, and what he thinks of the 'competition' between new languages.

I think it's only fair seeing as this article accuses Bjarne of "evilly shrewd" moves, maliciously crippling Cs development, and "knocking C it in to a coma". So watch it for Bjarnes perspective from his own mouth. You may as well see get a biased view from both sides.

https://www.youtube.com/watch?v=jDqQudbtuqo


Bjarne has been on a bit of a promotion tour recently. Here is another Q&A session he did with Slashdot on the 20th [0]. I suppose this is because of the recent standardization of C++14.

One thing I don't particularly agree with is that some of his examples of C++ code use features that will not be made available for years, likely around or after 2017 when C++17 should be standardized. This is assuming compilers implement the standard quickly, which is worse on some platforms than others (cough Visual Studio cough). What I'm specifically talking about is any example that mentions concepts, but at least he is clear that concepts are only currently available in a branch of GCC.

[0] http://features.slashdot.org/story/14/08/20/011231/interview...


> What I'm specifically talking about is any example that mentions concepts, but at least he is clear that concepts are only currently available in a branch of GCC.

The syntax for concepts seems pretty well set now, and Alex Stepanov (author of the STL, and worked with Bjarne on the new concept model), in his Amazon A9 lectures (available on YouTube) recommends you simply #define concept names to "typename" so they at least exist in your code as documentation.

The most important thing however is really to get people writing their generic code with a concious awareness of what their type requirements actually are, and then to document and specify them correctly, just like you'd rightly expect a function written in C99 to specify clearly what the pre and post conditions are... something the compiler can't help you with even today.


> This is assuming compilers implement the standard quickly, which is worse on some platforms than others (cough Visual Studio cough).

If your compiler isn't tracking the standard well, don't use it. The truth is that C++14 is just got ratified now and already open source compilers have implemented most of its capabilities. Concepts are a bigger kettle of fish, but compiler makers have also had much more time to work on them, so I wouldn't assume we have the huge lag problems we used to have with standards adoption.


Professional C++ programmer here, although previously I mostly worked in C# and python. I have to admit, I'm pretty ambivalent about the language. For a long time I loved it, and then for quite a while I really hated it (tracking down segfault that only happens on a release build on a tight deadline will do that to you). The thing is, all the terrible things people say about C++ are true; but what else is there in that space? It seems like most language design is aimed at a higher level. D seemed promising, but the whole standard library issue seemed to derail its momentum, and as nice as the language is, it's really complicated and the tool support kinda sucks. Rust is interesting but too immature to sell to the decision makers at most companies.

I understand people going back to pure C, but man, as screwed up as C++ is it's hard to give up things like vectors and strings and namespaces.

Everything else has a memory model that doesn't quite work, and look, I like GC as much as anyone but sometimes you need a language where you can turn it off when you need to guarantee there isn't going to be intermittent GC pauses.


Google's go and Mozilla's rust both fit the same sort of space.

Rust especially.


I do not see a double standard. There is a fundamental difference between PHP and C++. PHP was simply a bad design, needlessly ugly.

In contrast, the design of C++ was constrained by the goals of

- Compatibility with C (and later previous C++ standards)

- Zero overhead / you do not pay for what you do not use

- No GC

Those constrains are responsible for most of its ugliness, not poor design.


1. From a user's perspective it doesn't matter if it's "constraints" or "poor design".

2. Blaming C does not explain C++'s undecidable grammar, the zillion ABI incompatibilities introduced on top of C, lack of an alternative for #include coupled with features like inlining and templates making it a disaster that it never quite was in C, or many other of C++'s faults. How is PHP's grammar a worse design than C++'s? I really want to know. I think PHP's is better.

3. Source compatibility with C does nothing for the user (who could have lived with ABI compatibility just fine) and everything for Stroustrup (who managed to make his language that much more popular by an Embrace, Extend and Exterminate approach).

4. Design goals inevitably resulting in a bad language are bad design goals. If I said that I designed an electric car that electrocutes you but that's because it's compatible with an electric chair for which there's a lot of existing demand, would you then publicly defend me?

5. PHP is a child of Perl which is a child of shell, awk, sed and C. A lot of heritage there to blame as well. So?

6. PHP doesn't byte one's behind nearly as badly as C++ and that's why the double standard exists; because only a fraction of the people who try manage to ever get anything done in C++ and a large subset of these people feel entitled to be treated as an "elite". PHP programmers cannot afford to delude themselves thusly because everyone can be productive in PHP... A funny outcome, I find, given that it "should" have actually led to PHP being praised.


> 1. From a user's perspective it doesn't matter if it's "constraints" or "poor design".

Of course it does. If it's poor design, one just don't use the language at all. If it's constraints, any language that solves the same kinds of problems will be just as bad, and - life just sucks - one must stop complaining.


"If it's poor design, one just don't use the language at all."

For greenfield development, sure. Many and maybe most of us don't work in that space.


From a user's perspective it doesn't matter if it's "constraints" or "poor design".

Of course it does. I'm a "user" of C++ and all three of those constraints are very very important to me. There's pretty much no other language (in common use with lots of vendor support etc.) with the power of C++ that follows the same constraints. The constraints are the very reason that C++ is still so popular despite all the complexity (and seemingly an extremely hostile group of critics trying to warn everybody against using it.)


1. Wrong for reasons others have mentioned

2. PHP was never designed to even support objects in the first place. The API is super inconsistent in terms of parameter ordering and naming. Contrast that with the vast majority of the STL. Sources for the zillion ABI incompatibilities comment?

3. How about, oh, IDK, OpenGL being a C interface. Lua? The Linux kernel? X11? Driver interfaces in general?

4. The big presupposition here is that it's a bad language. Honestly, I'd like to see you design a language that does what C++ allows you to do much better.

5. C was arguably way better put together than Perl was. Perl is an abomination to be honest.

6. What are the use cases of C++ compared to PHP? C++ is used to do things like author renderers, or physics engines, or mathematical simulations. Trust me when I say that attempting to accomplish any of those to the same volume with the same hardware on PHP is madness.


1. Except for self-inflicted constraints that don't match the problem domain. Which leads to…

3. OpenGL, Lua FFI, Linux… have nothing to do with source compatibility with C. And everything to do with ABI compatibility. C-with-classes was a preprocessor that generated C code remember? That pretty much guaranteed ABI compatibility, since it was then compiled by the same C compiler.

But what did it matter if the pre-processor where also capable of parsing plain C? It doesn't! We have a C compiler, why not just use that? If stroustrup wanted to, he could have replaced the braces and semicolons by mandatory indentation, Python style, and lose zero backward compatibility in the process. Or at least, no compatibility that actually matters.

Source compatibility was a useless constraint that lead to a painful language. From the user's point of view, the difference between a useless constraint and a bad design choice is nil.

Now I will concede one advantage of source compatibility: learning curve in the extremely short term. If you don't even have a few hours to learn a different syntax, it makes sense. But if your intend to use a language for more than 2 weeks, it's silly to suffer any long term cost just because you don't want to pay that learning cost up front.


Source compatibility provides an upgrade path. This was useful when C++ was introduced, because it allows you to take an existing C program and incrementally start using C++ features. You could claim this is less important today, but I have a counter example. Look at gcc. It used to be written in C, but switched to C++ recently. Try that with mandatory indentation.


Upgrade path? Easy as pie! Just parse the C source, then pretty-print a mandatory-indentation version. As long as the new language has all the semantics of C, converting from one syntax to another is trivial. And if you insist on "incremental", you can do this one module at a time.

Seriously, stop listening to your guts and look at the facts.

As for gcc setting up some kind of example for upgrading to C++… C and C++ are low-level systems languages. They are not suitable for static compilers. While I understand bootstrap as a validation technique, it is not worth the hassle of suffering such a mismatch between the language and the problem domain.

Static compilers should be written in an ML dialect, or Haskell, or maybe Lisp. C and C++ have no business here. And if you really want the bootstrap thing, then you should also implement a DSL that compiles to C or C++, and use that to make your compiler.


Okay, if you literally have all the semantics of C, your idea works. But if you have ALL the semantics of C, why bother changing the syntax?

As for ML and company being a better choice than C++ for writing a compiler... There may well be convincing arguments for this position, and if I asked you, no doubt you'd give me some. But I'll ask something else instead. Most compilers I heard of are written in C or C++. Name me a compiler written in ML/Haskell/Lisp. There's just one rule: no bootstrapping. Meaning that if you show me a compiler for ML written in Haskell, that's fine, but a Lisp compiler written in Lisp is not.


> But if you have ALL the semantics of C, why bother changing the syntax?

Two reasons: first, change what sucks (like the useless clutter with braces and semicolons, or the switches that fall through by default). Second, add more features on top of what we have.

As much as I hate C++, we do live in a C dominated world, and C is… limited. The lack of a usable generics system is crippling. C++'s destructors really help with semi-automatic clean up. And it would be good to have a module system, and maybe built-in support for algebraic data types. (I must not overdo it: if I end up turning C into ML, I should use ML. Or Rust.)

> if I asked you, no doubt you'd give me some.

I'll give you one: Algebraic data types, which are virtually unmatched at representing abstract syntax trees, and basically any intermediate representation a compiler can come up with. Other arguments here: http://flint.cs.yale.edu/cs421/case-for-ml.html

> There's just one rule: no bootstrapping.

Of the top of my head, I don't recall any compiler that doesn't bootstrap. In any case, I fully expect that most compilers are indeed written in C and C++, not in ML or Haskell: C and C++ are that popular.

I also happen to think our industry as a whole is mostly nuts, retarded, and short-sighted.


You may well be right about that last part. But still, perhaps one day someone will write a C compiler in ML in record time and get people's attention.


I don't believe that C++ would have had undecidable grammar if it hadn't aimed for source compatibility with C.


What rubs me the wrong way is that it's not even C compatible. Trying to compile a C codebase with a C++ compiler is more likely than not going to give me hundreds or thousands of conversion errors thanks to the terser casting requirements. It's a worst of both worlds situation: Neither the ability to use C code as-is nor a clean grammar.

I also believe the grammar could have been made much better while maintaining C compatibility. The language design seems more like throwing stuff at the wall and rolling with whatever kind of sticks, than fully exploring the problem space. See the export keyword: implemented once, and then removed as worthless, not even bothering with the step of deprecation, at the recommendation of said implementation.


The undecidability arises from the way that C's lexer hack for types interacts with the way C++ chose to implement templates. There are other approaches to implementing generics that could have avoided this unfortunate interaction while remaining backwards compatible with C (as C does not have generics).


There also isn't a real alternative to C++ for many of the things it does. If you're writing an OS, JIT compiler, or a garbage collector, you're writing it in C or C++ right now. And due to frustratingly solvable problems like symbol collision, C does a terrible job of scaling to to large code bases.

In contrast, there are many languages that can do the job of PHP.

To be sure, there are languages that aim to challenge C++ on its home turf, but it will take a lot of time and a lot of work before you will see a relational database written in Rust (or insert your favorite C++-killer here).

EDIT: spelling and grammar


"C does a terrible job of scaling to to large code bases"

Linux says otherwise.


That's partly an exception that proves the rule and partly not a typical case. Uniquely, OSs get to reserve names for themselves (like time, syscall, reboot, etc.). Third-party libraries and other code have to do funny prefixing to avoid name collisions. OSs also have relatively few source code dependencies and, when they do, they get to dictate them.

There are other reasons that C doesn't scale well to large software systems. For example, C's relatively limited compile-time error checking, which leads to using conventions (especially naming conventions) to enforce good practices where tools and good typing would do the job better.


Exceptions don't prove rules; they refute them.

The actual origin of the saying is quite different:

http://en.wikipedia.org/wiki/Exception_that_proves_the_rule


I understand what the expression means, and that's what I meant (though perhaps I could have been more clear). *nix (and libc) are exceptional in that they got first dibs on the symbols they wanted due to being there first. So it proves (while justifying) the rule that you have to prefix all of your symbols unless you're Thompson or Ritchie in the 70s. Even now, in newer C features, extra acrobatics are done to avoid name collisions (_Bool in C99 for example).

But this is really a side issue to my original point: C++ and PHP are categorically different since there aren't strong alternatives to C++ for many types of problems. Though it is possible that other languages are eating at the edges of what C++ is good at.


You don't need to write large software systems in C or C++. Use Java. Or decompose it into components and employ Python.

But GC, VM, OS - all those TLAs can and should be written in kosher C.


Single data points never tell you a tremendous amount. People can and do write good software in languages that are poorly suited to the task all the time. No one is saying you can't do it; just that it makes your life significantly harder than it otherwise needs to be.

The success of C++ provides a wealth of evidence that C isn't really up to the task -- everyone seems to hate it for its complexity, but very few people are writing web browsers in C89 these days.


I would label your third point as a subcategory of the second, as it is impossible to have a garbage collector without having some sort of overhead.


> I would label your third point as a subcategory of the second, as it is impossible to have a garbage collector without having some sort of overhead.

It's impossible to have a heap allocator without overhead. How much overhead you have depends on the design constraints and the trade offs. Particularly if you are dealing with more sophisticated constraints like memory fragmentation and other issues, a GC might actually be an easier and lower overhead way of solving the problem.

More importantly, you missed the most important aspect of the second point: "you do not pay _for what you do not use_". You and copx would be surprised to know that pretty much since the standard committee started working on it, garbage collection has been something on the table for C++, but they've never been able to get a proposal that everyone was happy with.

I also think that the "No GC" category is perhaps not the right name. What C++ was really about was making UDT's first class types and therefore supporting value semantics. A side effect of that is that GC isn't nearly the priority it might otherwise be.


How about we put it this way: all forms of dynamic memory management have overhead, including malloc(). The overhead for garbage collection is different from the overhead for malloc(); GC is worse some respects (latency, space usage) but better in other respects (throughput, development time).

GC can be much faster than malloc() when allocating objects, depending on the GC scheme used and the heap profile, allocation savings may outweigh the cost of collection.

So "No GC" is a completely separate point.


Garbage collection does not offer better throughput than manual memory management, in fact it tends to need ~6x the memory to equal it[1].

[1] http://www.cs.umass.edu/~emery/pubs/04-17.pdf


I'd be wary of that paper: of the 5 garbage collectors they have tested, only one appears to be generational. That makes me doubt they used sufficiently state of the art garbage collection.


"Compatibility with C"

This is not a feature for a programmer to use to make their work easier, rather this is a hook to infect the code, spread the disease and live where other nicer things wither.

C++ is like mold. Yes it is ugly, and you don't want it, precisely because this is the most efficient life form compatible with your stale food, whether you want it or not.

Mold is the most popular pet people have, because it is so hard to avoid. Lice (PHP) were too, but today it was mostly eradicad thanks to better hygiene.


>This is not a feature for a programmer to use to make their work easier

It makes it possible to use C definitions directly and inline with no conversion overhead or indirection. When your work is writing fast code, the ability to leverage existing fast code damned well is a feature.

>C++ is like mold >you don't want it, precisely because this is the most efficient life form compatible with your stale food

You don't want mold because it causes respiratory and neurological problems. C++ does not cause respiratory or neurological problems, unless you count the insanity it inherited from C like, "A character is the same thing as a byte," "A pointer is the same thing as an array" (which isn't even actually true within the language, unless you count parameter declarations), and my personal favourite, "The mathematical value of false, the cardinality of the empty set, and the identity of nothing are all the same thing. After all, they have the same representation!"


> [Compatibility with C] makes it possible to use C definitions directly and inline with no conversion overhead or indirection. When your work is writing fast code, the ability to leverage existing fast code damned well is a feature.

That is achieved with ABI compatibility. You don't need source compatibility however. At worst, you'd have to re-write the prototype of the C function in your own syntax-incompatible language.

Think of it as a zero-overhead FFI.


>re-write the prototype

>ABI compatibility

In other words, conversion overhead and indirection, respectively. There is no substitute for having an inline definition available at the point of use.


Oh. I thought you were talking about runtime overhead. "Fast code" and all.

Well if you're worried about writing overhead, there are many FFIs out there that parse the header you want so you don't have to repeat anything.

But if you believe for a nanosecond that we need source-level compatibility to get the benefits of inlining… Just remember how C++ first worked: as a pre-processor, that generated C code! So it's all C underneath, and GCC and LLVM and MSVC and ICC can all do their crazy optizations accros the whole project, should you need that.

And in any case, C++ is no longer source-compatible with C. And it no longer work as a pre-processor either. Yet I doubt it has the disadvantage you talk about. C++ has many faults, but overhead with the C FFI is not one of them. Which means we have an existence proof for the assersion that source-level compatibility is. not. needed.


>if you believe for a nanosecond that we need source-level compatibility to get the benefits of inlining

You do. Yes, there's LTO, but to do it effectively relies on storing source code or information derived from it in the intermediate object files. Without the source, the best you can do is try to inline what is hopefully a reasonably well-behaved hunk of object code without any of the high-level information associated with it that the compiler threw away when it emitted it.

>C++ has many faults, but overhead with the C FFI is not one of them [...]

I'm not sure exactly what you mean, but if you're talking about the runtime overhead of calling an extern C function, then that is very much a fault. Inlining can make all the difference in the world with respect to performance in an inner loop, the classic example being qsort and std::sort, and to take advantage of that, source-level compatibility is needed.

Now, if you said that source-level compatibility were better achieved using a fully-fledged FFI than by stuffing all but the worst (well, some of the worst) of C into your language, I would whole-heartedly agree with you. If C++ had done the former, it would be a much cleaner, much less popular language, and instead of using a warty language with templates, useful user-defined datatypes, and function overloading, we'd all be using a warty language without templates, useful user-defined datatypes, or function overloading. Hell, many of us still do anyway.


> C++ is like mold. Yes it is ugly, and you don't want it, precisely because this is the most efficient form for it to be able to colonize your food.

Why does any mention of C++ bring out these silly metaphors that contribute nothing to the conversation?


I've been using C++11, and I really like it. Together with RAII it seems entirely modern and reasonable.

Is there a list somewhere that describes what the "bad parts" (in the Crockford sense) of C++ are? Bad practices, bad feature interplay, etc.

I've been thinking of writing a little C++ transpiled language of a limited feature set to make prototyping certain things easy. It would try to follow the accepted best practice conventions. I imagine it to be Coffeescript-like, with no separate header files, support abbreviated syntax, syntax for managed pointers, etc. It would probably follow a rudimentary linking scheme.

It might be opinionated in ways that turn some people off: const vars and args by default, virtual methods by default, auto virtual dtors, and probably other "sensible" (in average usages) default patterns.

Finally, I would want to generate simple intuitive interfaces that are linkable to existing C++ headers.

Anyways, this would just be a side project for fun. I don't do C++ professionally. Just for robotics and lasers and hobby stuff. Any information on best practices and bad C++ usages would be awesome to have if I undertake this.


C++ is somewhat notorious its developers' practice of selecting different subsets of C++ as "the good bits". I think one of the biggest mistakes of C++ was conflating the three different concerns of record types, polymorphism, and encapsulation. All three are bundled up in the catch-all "class", and everyone comes up with their own workarounds which should have been language constructs to begin with. So you'll end up with a language which enforces your C++ style.

The good bits everyone agrees on are parts like <algorithm>, and oh man, I have a hard time imagining how you'd make that easy to follow.


I hear the "different C++ subsets" meme all the time. To the best of my knowledge, this is typically cited in relation to template generics, exceptions, multiple inheritance, and RAII being used incongruently. IIRC, Google chose not to use exceptions, but this might be unrelated. (ex-googlers I know have mentioned that Google doesn't care about C++ services terminating and having to be respawned)

Your comment kind of makes me question my understanding of the different subsets issue... Would you mind elaborating? I could really stand to understand this better. If you can't expand on it, thanks for giving me something to look into. :)


In particular:

* Inheritance-heavy subsets, which avoid templates in favor of dynamic dispatching.

* Template-heavy subsets, which avoid dynamic dispatching in favor of templates.

* Subsets avoiding exceptions.

* Subsets avoiding RTTI (dynamic_cast and friends).

* Subsets avoiding pointers (including smart pointers).

* Subsets avoiding the use of container libraries.

* Subsets avoiding the use of <string>.

* Subsets avoiding the use of <iostream>.

You can search for large projects' style guides. For example, Clang uses C++11 features BUT they avoid RTTI and exceptions, which is a relatively common choice.


You might be interested in Haxe [1] and Felix [2], although both have broader scope than you indicate.

[1] http://haxe.org/ [2] http://felix-lang.org/


Felix looks really interesting, especially with regard to the first class functional aspects, how they implemented their stack, and the user extensible grammar. I might actually find myself distracted by this instead. :)


I am dreaming of something similar. I'd like to see a simple language wich looks a bit like python and compiles to C++. The central part of this language would be an integrated package manager / module system which replaces make / cmake. Why should I need make? I just want to tell the compiler the file with main() and then it should figure the rest on it's own.

The one thing which stops me from writing more c++ is all the setup you have to do to actually get an executable. In python I can just create a file, import some stuff and run it. In C++ I have to deal with makefiles, vs projects, paths and all that crap. Just give me a C++ where I can write "import boost.xyz" and the compiler figures out what that means.


Actually, I put a c++ project template together to solve this exact problem. It uses cmake to generate a makefile (including IDE projects that just work), and google mock for testing. You still have to add libraries like boost to the CMakeLists.txt if you want to use it, but it's really easy. Just follow the examples in the project.

Github: https://github.com/film42/cpp-starter-template/


Got a way for me to contact you? I'll cc you with a github link if/when I get around to this. Would love early design feedback. Alternatively, you can email me from the info in my profile. No worries if not interested, of course.


Have you checked out http://nimrod-lang.org/ ?

It compiles to C though, not C++.


I'd check out Nimrod for some inspiration: http://nimrod-lang.org/

It has a bit more of a Pascal flavour to it, but it is the nicest implementation of a compiles-to-C languages I've seen.


So the original guide seems not to have been updated since 2009 [1], and even then only in minor ways. Are these criticisms still valid of C++, even without the C++11 standard? Clearly the language issues won't have gotten any better (without C++11), but many of the arguments in the FQA seem to call into question the correctness of the compiler or the quality of the compiler's optimizations (see e.g. [2] and [3]). Is this still valid for modern compilers (GCC 4.8, Clang 3.4, etc.)?

[1]: http://yosefk.com/c++fqa/changelog.html

[2]: http://yosefk.com/c++fqa/ctors.html#fqa-10.9

[3]: http://yosefk.com/c++fqa/templates.html#fqa-35.10


No. There was a time when you couldn't count on a lot of C++ features being fully or correctly implemented, but that time has passed. A lot of the other arguments revolve around slow compile times, which are fixed by having plenty of fast hardware. Most of the remainder are divided between matters of taste, and genuine sharp edges you have to be careful to avoid.


> And Stroustrup says about himself that he "lacks marketing clout" and says Java and C# are bad for you because they're "platforms, not languages", whatever that means.

Perhaps Stroustrup is referring to the JVM and CLR, respectively?


Right. Java-the-language depends heavily on JVM-the-environment to be usable. Without an excellent GC (sometimes even with one) common coding patterns are unworkable, and the design of the language lends itself heavily to GC-dependent overall designs. There are also aspects of the implementation details that dominate language design (eg, primitive boxing and the generics implementation).

That said, if you know what you're doing it's a great platform.


These kinds of rants sadden me. They purport to outline absolute, logically inviolable reasons that a given language is "bad". What they really do is express the writer's frustration, an emotional reaction that probably emerged from working with language attributes and features that he in some cases doesn't understand well or in other cases simply doesn't prefer. C++ works beautifully for millions of programmers who happen to "get" it and like it, just as Java does for others and C# does for others and Haskell does for others and fill in your main squeeze here. Programmers are trees (http://www.jeffwofford.com/?p=915). We each adapt to what we like and come to like what we adapt to. Let's not pretend we alone have the One True Way or that our non-preferred way is stupid.


To be fair, YosefK's FQA is a truly great piece of work, and something that every seriuos C++ developer really should read and internalize. The criticisms in it, both of the language and the culture around it, are biting and valid. And it's a fun read too.

Really I think one of the best things to be pointed out about C++11 is that YosefK's response is... a little disappointing. Sure, he makes some good points (I liked the "array[5]={0};" mistake), but really this isn't nearly as strong an indictment as the original was. Frankly modern C++ is a huge step forward (though obviously traps remain), and this is as good evidence as we'll see.


I get the feeling the anguish arises from working with a large codebase with varying quality of developers. For me the main problem of C++ as a language is that it is marketed as a general purpose programming language while in reality only particular types of developers are capable of using it properly in an industrial context. You have to be an a) expert with b) a good taste or the whole codebase will in time become unmaintainable and/or unstable, or both. And even in the best case scenario there will be horrible bugs arising from some minutiae you forgot to take into account.

The expert part is required just to cope. The good taste part comes from the requirement that other people must comprehend your code. i.e. it needs to be simple, pithy and correct. Some languages make it more obvious how to reach this goal than others, while in C++ I see this being mostly the result of trial and error. You require taste, restraint and experience not to implement your production solution in some unmaintaineable template-class-Gang-of-four mishmash "just because you can" and because "it's the C++ way".

The main problem with all this, IMHO, is C++'s continuing popularity. There are some problem contraints where it still is the best tool for the job but those contraints should be well understood and realized when selecting it as the implementation language.

> C++ works great for millions of programmers who get it

I feel this is a huge productivity loss for the industry as a whole. C++ creates a huge bureaucratic burden on the developers where they must spend their efforts to trivial minutiae and not in value adding work. C++11 improves on this considerably, though. I do not presume to impose some other language on those developers - rather my point is that the issues the FAQ author raises are real and that since lots of people are using the language the severity of these issues is multiplied by the number of people using it.

Note: I'm a developer who mostly writes C++ in an industrial context :).


While your point may be valid... let's also not pretend that some genuinely bad solutions are just "non-preferred" ways and that C++ is not without it's shortcomings and hidden pitfalls. After all, there is a reason that any style guide for C++ will include a large list of features that should not be used.

I love the language and use it alot... but sadly, in many ways, this FQA is just too true.


You're just reinforcing the parent's point. Take this sentence:

> <PROGRAMMING_LANGUAGE> is not without it's shortcomings and hidden pitfalls. After all, there is a reason that any style guide for <PROGRAMMING_LANGUAGE> will include a large list of features that should not be used.

This holds true of pretty much any language. Take a look at Google's extensive style guide library [1]; they all contain language features that should be avoided for any language. It all just reflects the iterative nature of programming language design.

[1] http://code.google.com/p/google-styleguide/


Look at Google's Python Style Guide: http://google-styleguide.googlecode.com/svn/trunk/pyguide.ht...

There is almost nothing in there that sounds like a landmine. Rather, some general guidance about "don't use global variables," "x may not be thread safe," and "don't write overly complex lambdas."

My favorite "gotcha" in Python is using e.g. a list as a default argument. That's in the guide, and it sucks, but Python has surprisingly few such problems for newcomers.


I can think of two landmines that make most C++ issues pale. First is things blowing up at run-time due to typos or syntax errors. Second (related) is that you can't safely refactor because you don't really know the types that functions take or where they're being called from. Sure C++ can be a pain but you can build and maintain very large software in C++. It's a lot harder to do in Python (without taking other considerations into account).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: