One small comment - what makes C++ appropriate for my usage is mainly templates. Lots and lots of templates.
It is very useful to be able to easily compile an algorithm for different types. If compiling a whole 10,000+ line algorithm 4 times for char/short/int/long inputs with templates and doing run-time branching between the algorithms (but not in the algorithms) saves 15% CPU time, then that is well worth the work. I don't know (well) any other language that offers that. Obviously if you introduce some kind of abstract base class / interface like Java, you will immediately lose the benefit of going int -> short -> char, when a class is alway at least... 12 bytes? 16?)
In C doing that requires a lot of macros and rapidly gets unusable, in Java it requires introducing lots of interfaces and hoping things get inlined.
What I like about C++ (compared again to Java/C, not Haskell), is that I can without fear of cost (other than compile time) introduce another layer of abstraction. When benchmarking code this is amazing, I can easily swap in a vector, or a deque, or an optimised fixed-size stack array.
In Java it is common for people to 'un-Java' code, introducing arrays of primitives instead of arrays of classes for example.
I don't know how well Haskel does at that kind of thing.
I think C++'s template feature is pretty unusual in languages. Lisps have macros, which are much more fully-featured and more hygienic than C macros, but I don't think any Lisps are fast enough to be interesting to you. I know that the Scala community is working on putting macros in.
Have you looked at Ocaml and Scala? Those might be close enough to suit your needs, and I think it's only a matter of time before Scala (or something like it) starts outperforming C++ on parallel problems.
What I'll say for C++ is that, in the style of development you're doing, it's definitely faster. The problem I have with C++ is all the use of it that occurs where it's not appropriate and actually makes performance worse because per unit time, programmers can accomplish less in it.
It's clearly possible for expert programmers to optimize the hell out of C++ in a way that just doesn't exist in GC languages, but I don't think average-case code is better, especially if it's framed as an economic problem and programmers of equivalent skill are involved and given the exact same amount of time to do it. Under those constraints, for a large problem, I would bet on Ocaml and Scala winning just because the programmers would have more time to spend on optimization. For a small problem, though, I'd bet on C++.
C++ template's aren't just unusual, they're unique among mainstream languages. They're C++'s secret weapon. These days, if you're not making heavy use of templates in your C++ code then you're using the wrong language. Like you said, many people use C++ to solve problems they could be solving more quickly and more safely with another language, but it's not C++'s fault, it's their fault.
In particular, the key feature of C++ templates (as opposed to other similar systems of polymorphism) is that they abstract over not just code but data representation. This is what CJefferson was getting at and it's orthogonal to macros. Ocaml and Scala don't offer it. It's about data, not code, so you'll never be able to gloss over it with extra parallelism.
In C++ a std::pair<double,double> really is just two doubles, 16 bytes. It can be passed into and returned from functions in registers. If I have a singly-linked list of them, each list cell is 24 bytes (16 for the pair, 8 for the next pointer.) In any other (mainstream) language, the pair is really a pair of pointers to boxed doubles which reside in the heap, and the list cell holds a pointer to that. The overhead of this is unacceptable in many situations, and these situations are where C++ still thrives. (cf. the Eigen linear algebra library for an example of "doing it right.")
Most languages have given up on this feature because of the drawbacks (code bloat) and the unified runtime representation of data (basically everything is a void*) makes many things easier (garbage collection, serialization, etc.) (I'm not super familiar with C# but I understand the struct types address this somewhat, but not without their own drawbacks.) But thanks to LLVM (written in C++ btw) people are pushing this area of language development forward (Rust, Deca, and others) in an attempt to fix the (many) problems of C++ while preserving its strengths.
Oh and BTW: A tank with wings is called an A-10 warthog :)
> I think it's only a matter of time before Scala (or something like it) starts outperforming C++ on parallel problems.
It is certainly plausible. But a few things need to change
(i) JVM applications tend to be memory heavy, even if you can approach 75% of the run time speed of a C or a C++ application you would typically need a lot more memory. In my expeience it has been 8 times or more, YMMV.
(ii) The other problem is that all the exciting native SIMD instructions are mostly out of reach. This can be a drag especially when your code uses log and exponentiation a lot. Without SIMD they are terribly expensive.
(iii) The kind of things that I use C++ for is heavy in array operations, in particular manipulating sparse arrays. In these applications the loop bounds are not constant and it is impossible to ensure at compile time that the array indexing will not go out of bounds. There Java's runtime bounds checking does slow it down. A way to override the safety would help.
(iv) The other good thing about C++ is the ability to delay evaluation via the use of templates, I am talking about expression templates. Its not pretty by any one's standards but with suitable libraries you can get the job done.
> I don't think any Lisps are fast enough to be interesting to you
Under favorable circumstances Lisps can easily give C++ a run for its money, even on numeric code. For that take a look at Stalin. It's unbelieveable how much one can optimize, even without type annotations.
There are few new curly brace languages out there, that are trying to simplify generic programming. D is the more mature among these and the new exciting ones are Clay, Deca and Rust. All have been discussed on HN. Exciting times ahead.
A multithreaded runtime for OCaMl will be realy cool. I do not need that threads be surfaced as an API but the possibility that parallelism exposed by the functional style can be exploited by the runtime (perhaps based on options used to start the runtime).
Yes there is F# but mono I hear is not that great on Linux, though I have not tried it myself.
A multithreaded runtime for OCaMl will be realy cool. I do not need that threads be surfaced as an API but the possibility that parallelism exposed by the functional style can be exploited by the runtime (perhaps based on options used to start the runtime).
One small comment - what makes C++ appropriate for my usage is mainly templates. Lots and lots of templates.
It is very useful to be able to easily compile an algorithm for different types. If compiling a whole 10,000+ line algorithm 4 times for char/short/int/long inputs with templates and doing run-time branching between the algorithms (but not in the algorithms) saves 15% CPU time, then that is well worth the work. I don't know (well) any other language that offers that. Obviously if you introduce some kind of abstract base class / interface like Java, you will immediately lose the benefit of going int -> short -> char, when a class is alway at least... 12 bytes? 16?)
In C doing that requires a lot of macros and rapidly gets unusable, in Java it requires introducing lots of interfaces and hoping things get inlined.
What I like about C++ (compared again to Java/C, not Haskell), is that I can without fear of cost (other than compile time) introduce another layer of abstraction. When benchmarking code this is amazing, I can easily swap in a vector, or a deque, or an optimised fixed-size stack array.
In Java it is common for people to 'un-Java' code, introducing arrays of primitives instead of arrays of classes for example.
I don't know how well Haskel does at that kind of thing.