C++ 17 is Done
herbsutter.com
herbsutter.com
http://stackoverflow.com/questions/38060436/what-are-the-new...
std::optional and std::any are one of the good things. std::apply and std::invoke can help you write better functional c++17 code.
Anyway thanks for C++17. For sometime, I thought I will learn Rust.
I faced the similar problem. I invested some money in Effective Modern C++(Scott Mayer). It covers the language part. I borrowed a book for C++11 concurrency. But, modern C++ lacks high-quality material at one place like Golang/Rust(the language guys have very good documentation, not boring and good enough to learn quickly). There are tons of scattered example.
This comes pretty close to what you're asking for I believe.
On x86_64 Linux, it looks like a function with signature `void f(std::variant<int, char>)` expects its (8-byte) argument to be passed by reference, whereas `void f2(tagged_union_of_int_and_char)` passes its argument in rdi.
gcc (-O3) also generates miserable code for calling f(42):
4004f0: 48 83 ec 18 sub $0x18,%rsp
4004f4: 48 89 e7 mov %rsp,%rdi
4004f7: c7 04 24 2a 00 00 00 movl $0x2a,(%rsp)
4004fe: c6 44 24 04 00 movb $0x0,0x4(%rsp)
400503: e8 c8 ff ff ff callq 4004d0 <f>
400508: 48 83 c4 18 add $0x18,%rsp
40050c: c3 retq
as compared with calling f2(42): 400510: 48 bf 00 00 00 00 2a movabs $0x2a00000000,%rdi
400517: 00 00 00
40051a: eb c4 jmp 4004e0 <f2>
std::optional seems to have the same disease; the ABI is different from a plain struct containing a bool and the value and you get worse initialisation code. There's also a build time penalty to using std::optional; on my machine, including the code that uses optionals makes my trivial test program take 320ms to compile and link rather than 50ms.These look like yet more new C++ features that are worse than what they're trying to replace.
I would also agree that pure performance and deterministic memory management are the two main reasons to use c++ for a new project nowadays.
For the parts of the codebase where you count cycles, you often want to carefully lay out the data and then use hand coded SIMD. Possibly use a specialized code generator that writes the SIMD asm for you, with less chance of error. If you can't do SIMD, I would just use C, but use a safety-critical code standard for the C part.
Existing codebases and existing investment into learning C++ arcana complicates these decisions, but I truly believe C++ is not worth it for new projects.
So what would you use if the constraints for the project are of the usual C++ kind? I.e. language has industrial support, proven toolchain, loads of potential candidates who can write the language, the code will compile 20 years in the future, can tightly integrate with a gui ... etc. Honestly, if there is a better language where I percieve C++ to be the best language I would dearly like to know. Half of the reasons I use C++ have nothing to do with the language itself but of the modern computing ecosystem.
It's okay to admit that you like C++, it's what you know best, and that it's not unsuitable for the things you want to do. The same as someone else says that about F# or Lua.
But that's not what you and others are arguing here... instead you're arguing that there are no reasons to use C++ and one should use other languages instead. Which is pure nonsense.
One is a limited number of "computation kernels" (processing packets, processing transactions, computing a photoshop filter) that need to be very fast but can be carefully generated/handcoded in C or SIMD asm or whatever that has very simple behavior/API, for example it should not allocate memory.
The other part is the complicated part that has all the complex behavior (a lot of code, changing business requirements, opportunity for abstraction) that configures the kernels and feed data into them and interacts with the user and the network but takes a small part of the CPU time.
The second part must be organized so that it will not inhibit the first part in any way, so that means the second part can't use a language that won't let you layout stuff in memory in exactly the way you need or that has poor cffi performance.
The second part can be done in something as slow as cpython! (though it doesn't have to be quite that slow).
It would be simpler next time to just state that C++ is not a must for all software. But we already know that, so maybe the whole discussion can be skipped.
I think your approach is "default to C++ because of very broad support, write the cold code and the hot code in C++, optimize the hot code" and implicitly you also say "and damn the security and maintainability implications".
My approach is "use the safest and most maintainable language for all code that can tolerate the performance impact", so I would prefer to write everything in a higher level language than C++ and optimize using cffi, asm, etc. only the inner most loop.
Maybe modern C++ can overcome the weight of backwards compatibility and create a truly modern subset that is as safe and as pleasant to work with as newer languages. Then your approach would definitely be better. But I don't think we're there.
For example, I think of things like a web server, where the AES-GCM has to be assembly, the HTTP parser should be generated by a special tool and the rest should be in a memory safe language to avoid Cloudbleed. Can modern C++ be that memory safe language? If yes, I'm wrong.
C++ isn't used only for generating the fastest possible code, but also to generate code with predictable performance, code that is default-fast and code that can be optimized without the fear of having to change programming languages to reach a performance goal.
* it's platform-native on the major platforms and many others
* it's an international standard and has excellent backwards compatibility. i.e: it's not controlled by some corporation and it's very unlikely that a 2v3 Python-style fiasco would happen.
* it has a huge ecosystem. The only comparable ones are Java and maybe C#, but while there's overlap, each ecosystem has its focus. Java's is focused on the back-end and enterprise development.
* it's a flexible and powerful language
* it's basically the default option in certain domains
void f(std::variant<int, char>)
would be f(x: IntOrChar)
roughly in Rust, I'm too lazy to make the types _exactly_ the same, but https://godbolt.org/g/pZde2A is roughly it.Actually, https://godbolt.org/g/1vcMeG might be even better to compare; I'm not an expert, but looks like the only difference is in the size.
last one, adding inline(never) so you can see the calls in main: https://godbolt.org/g/cVDjQH
movabs rdi, 21474836480
call example::f1@PLT
vs mov edi, 5
pop rbp
jmp example::f2@PLT
so, yup.In other words, the compiler can turn an Option into a null-pointer convention by reasoning from first principles.
(I think this optimization works for enums in general, and is somehow related to the `nonzero::NonZero` type, but I could be wrong about that.)
Example (look at the calls to f1 and f2 in example::main): https://godbolt.org/g/SSs6X2
(I know nothing about std::variant yet.)
In most cases, I imagine the performance penalty would be dwarfed by the cost of actually using the class.
Now why it is not trivially copy constructible is another question. But the latest standard draft does not require it [variant.ctor] though it does require the destructor to be trivial if all type destructors are trivial [variant.dtor]. The GCC implementation also seems to ensure only trivial destructor not copy constructor (the code is here [1] if anyone likes to see).
EDIT: I did a small experiment that agrees with this - adding a copy constructor causes passing by pointer. https://godbolt.org/g/UG0YXJ
EDIT2: I filed a bug report for gcc, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80187
[1] https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-...
It should be possible to implement std::variant in such a way that it is trivially constructible and destructible as long as all elements are, but apparently stdlibc++ doesn't. This is GCC choice and other compilers apparently do differently. Unless GCC changes it before finalising their c++17 implementation, the choice will be unfortunately set in stone for them as they guarantee abi stability of the library.
P0602R0 is a proposal to require trivial copy/move (but strangely not destruct), don't know whether it has been accepted though.
I mean modern C++, with all lessons learned, all revisions thus far assumed to be supported, officially and unofficially deprecated coding styles marked in helpful tidy little "Don't do this and this is why!" red warning boxes. Bjarne Stroustrup himself said C++11... _11_ almost felt like a new language, and here we are already!
C++ is so big, and not only that, changing so much. I have a hard time catching up and a distilled "sum of knowledge" C++ programming language guide would be immensely helpful. C++17 including all its predecessors almost feel more like D at this point, soon enough only missing GC compared to that, which by itself have alternatives in modern C++ that some argue is even better.
I also think there's a disconnect in how people perceive C++ today. Many seem to think of an archaic language, Quora questions "Are C++ worthwile to learn today?" abound... Another argument for a high visibility language guide being useful?
Documents like these are helpful but not very easy to digest: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppC...
And I do consider, that some of the strongest criticism of C++, and that is, "that most people use a subset of it, so it feels like many different languages glued into one", is actually a strength .. it means you can ignore some the complexity .. until you want it, or need it
I am very happy, that C++ is adding new features every 3 years .. and I do plan to invest more time in C++
Complexity is good
And I think that's a major reason why C++ usage is gradually becoming a niche thing used only where absolutely necessary. As evidence for that claim I submit this chart (you need to scroll down a page): https://www.itjobswatch.co.uk/jobs/uk/c++.do
C++ used to be required for over 30% of all permanent programming jobs in the UK back in 2005. Now it's down to 8.5% and falling. That's in stark contrast with all the enthusiasm created by the features added since C++11, features that I very much welcome.
Programming is more accessible than ever before, more jobs require some element of programming than ever before, and more things are getting created using code. This means that people who have never written code before are writing code as a job of work, and are writing it in simpler-to-learn languages.
Newer, simpler programming jobs are acquiring programmers in other languages, not necessarily that C++'s complexity is driving people away from it into the arms of other languages or that C++ is not acquiring newer programmers at the same rates (on existing base) as before.
It would be interesting to know if the share of developers with formal training has risen or fallen in the past 12 years. I would have guessed it has risen in spite of a large number of JavaScript wielding web designers.
There used to be quite a lot of DIY programming using VB6, VBA, Excel, MS-Access, dBASE, FoxPro, etc, at a time when professional IT departments and cloud services were not as widespread as they are today. In my opinion these technologies were a lot more accessible than the current web platform.
As much as I complain about C++, I just don't think there's a viable alternative, and I somewhat reject the notion that writing performant code is a niche thing. Like, sure, there are common contexts where you can get away with wasting CPU, but IMO part of being a skilled professional programmer is getting the most out of the machine, and you just can't do that with most other languages.
It surely isn't, otherwise we wouldn't be getting wind back into going native sails, with Swift, Rust, Go, Crystal, D, .NET Native, CoreRT, Java 9 (just a little bit, more with 10)....
Fyi, when safety is important and C++ is the only viable alternative, there's SaferCPlusPlus[1].
And wrt new C++17 features, I'll just point out that the SaferCPlusPlus library provides a version of std::any (and std::variant) geared specifically for pointer/iterators. That is, you can, for example, dereference the contained pointer/iterator without needing to know its actual type. And for those that need it, it also provides the "recursive_shared_timed_mutex" that's notably missing from the standard library.
[1] shameless plug: https://github.com/duneroadrunner/SaferCPlusPlus
If C++ is your only hammer then every problem looks like a nail to you. Of course, there are viable alternatives. At least Ada which is still used in avionics and other safety critical systems.
Like Ariane 5? :->
The crash was caused in part by failing to catch an exception in Ada.
http://sunnyday.mit.edu/accidents/Ariane5accidentreport.html
http://compgroups.net/comp.lang.ada/ariane5-faq/1406823
And yes, Ada is still used today.
Ada is an interesting language (we were taught it as our first language at uni), but it's not free from safety issues.
The flaws C++ were the reasons why Rust was invented. Mozilla wanted a safe language for the next generation of browsers, and they realized that C++ is not a good choice for safe programming.
Quote: "Mozilla intends to use Rust as a platform for prototyping experimental browser architectures. Specifically, the hope is to develop a browser that is more amenable to parallelization than existing ones, while also being less prone to common C++ coding errors."
Source: https://www.quora.com/Why-is-Mozilla-developing-the-Rust-lan...
That's true if you work alone. If you work in a team, it's almost guaranteed that someone will love using advanced features just for the sake of using advanced features, creating insanely verbose and abstracted behemoths which are bad both for the human developers and the machines to read.
I suppose it's good for job security...
Having poorly thought out complexity and no complexity often result in similar ends.
Honestly, I've seen C++ code so muddled and obfuscated that I actually wondered if those devs just wanted to make themselves indispensable. I really dislike such an attitude.
This is also in my case anywyay a barrier to entry or at least a point of intimidation. Where do I start? Which subsets are essential? Which version should I start with if I am learning today?
There are some domains and industries that break from these guidelines (or similar subsets) for various reasons, but generally speaking this is the sensible approach to take.
[0]: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
I believe in exactly the opposite. I always try to follow the KISS principle (Keep it simple, stupid) whenever possible since it always turned out to be the most reliable and maintainable solution.
It is funny that the first Ada versions (93 and 95) were considered vastly more complex in comparison to C++ in those days. Today it's the opposite. Ada looks like a clean mature language which only adds features which are actually needed. C++ wants to copy everything, attempting to squeeze every new feature into its narrow syntactic framework while still suffering the legacy of C and old C++ for reason of compatibility.
The only reason (IMHO) to learn C++ today is for maintaining legacy code in business. In all other cases there are better typed languages - Ada, Rust, and Nim for instance.
C++ may look nice at the basic level. As soon as things get serious C++ devs have a tough time. How does the experienced C++ dev fight that? He looks into his long list of tips and nostrums which hie collected in all his years to avoid all the pitfalls and minefields of C++. I don't believe that will change significantly with C++17.
C++ needs a linter that rejects code that doesn't meet a certain standard ala Rubocop.
The same that micro-optimize every single line of code they write without ever running the code through a profiler.
Matrix multiplication is super simple. Strassen is more complicated. Coppersmith–Winograd is brain bending (besides being slower on actual data and hardware).
The rule of thumb is: you have a complexity budget and a performance budget. Know what they should be, and choose economically.
If you mean the warnings, it's because they're way over the top.
switch(enabled)
> warning: switch on bool
switch(static_cast<int>(enabled))
Sigh.Now I know, "why would you ever switch on a bool?! It's only two possible states!"
Because it was in an ARM CPU emulator that decoded three to five fields per instruction, most of which were multiple bits long, but a few were just one bit. It gave a structured, consistent look to the code for each field to be implemented with a switch.
That's just one example, though. My current list of, "are you kidding me?" warning disables for Clang are:
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wempty-body"
#pragma clang diagnostic ignored "-Wparentheses"
#pragma clang diagnostic ignored "-Wreturn-type"
#pragma clang diagnostic ignored "-Wswitch"
#pragma clang diagnostic ignored "-Wswitch-bool"
#pragma clang diagnostic ignored "-Wtautological-compare"
#pragma clang diagnostic ignored "-Wabsolute-value"
This was all for perfectly legal, unambiguous code. Anything even remotely suspicious I'd fix. You probably still think I'm a macho coder anyway, but I'm honestly not. I'm just rather obsessive about consistency and simplicity in my code.I would really not enjoy working on a codebase that forced me to use -Wall -Wextra -Werr.
>= 0 on an unsigned value is the classic one.
Another time I've used it is just pure aesthetics:
if(addr >= 0x0000 && addr <= 0x7fff) return ram.read(addr);
if(addr >= 0x8000 && addr <= 0xbfff) return cpu.read(addr);
if(addr >= 0xc000 && addr <= 0xffff) return apu.read(addr);
Looks nicer than: if(addr <= 0x7fff) return ram.read(addr);
if(addr >= 0x8000 && addr <= 0xbfff) return cpu.read(addr);
if(addr >= 0xc000 && addr <= 0xffff) return apu.read(addr);
And the compiler will delete the unnecessary comparison anyway, so there's no great reason to warn about it.And now imagine you want to make it even nicer, so you add between(addr, lo, hi) as a macro: (note: not a real example -- I wouldn't do this for this case, just for demonstrative purposes.)
if(between(addr, 0x0000, 0x7fff)) ...;
if(between(addr, 0x8000, 0xbfff)) ...;
if(between(addr, 0xc000, 0xffff)) ...;
Now you have the generic code triggering the warnings again.Every warning case I've described can result in bugs, but the problem is when you intended to do what you did, you can't get the compiler to shut up about it there.
For the warnings I disable, they're things I do all the time. I can't recall ever typing = when I meant ==; whereas I combine assign + test into a single statement very frequently.
The warnings I keep on are the ones where I'd never want to do those things, and it'd never be proper code. Those are great warnings to have in place.
weird_non_trivial_copy_constructor_type foo() {
switch(value & 3) {
case 0: return a;
case 1: return b;
case 2: return c;
case 3: return d;
}
}
You can fix it by adding a default:, which will generate worse code; or by adding a dummy return (usually easy, but not always) after the switch; or by using compiler-specific intrinsics like __atribute__((unreachable)). Or you can turn off the warning.If they add [[unreachable]] to the standard, then I'll consider switching to that and re-enabling this warning. Because I'll admit, I have made the mistake of omitting a return type before.
For gcc and clang I've also had some success with the diagnostic pragmas, which I stick in pshpackN.h-/poppack.h-style header files. For example, I use these to stop both moaning about flexible array members in C++ code.
Push header:
#ifdef __GNUC__
#pragma GCC diagnostic push
#ifdef __clang__
#pragma GCC diagnostic ignored "-Wc99-extensions"
#else
#pragma GCC diagnostic ignored "-Wpedantic"
#endif
#endif
Pop header: #ifdef __GNUC__
#pragma GCC diagnostic pop
#endifEDIT: In particular, the clang tidy linter has a way of checking your code against the C++ core guidelines [2], which is a set of modern best practices for the language.
I've never met a linter I liked more than a real compiler, not even close. Linters for scripting languages only exist because the scripting languages aren't compiled, and they are only lightweight second rate optional type checkers. Linters' attraction and usefulness is that you aren't required to use them, so you can iterate quickly and run code without having to wait for the compiler every single time you save your file. Linters are not better at keeping you within good style and safety bounds, generally speaking.
Yes, a bare minimum standard, which must be backwards compatible. What a compiler enforces is not best practice, it is bare minimum. Something enforcing best practice has to be allowed to be backwards incompatible, since newer better ways of doing things will always come up (that's how languages evolve), and you want to discourage the older stuff.
"I've never met a linter I liked more than a real compiler" -- it's not an either or situation, use a linter on top of the compiler.
-Wall gives you a lot more than bare minimum. But, you can't really call it bare minimum when you compare compilers to linters in general. If a compiler enforces bare minimum, then a linter enforces less than bare minimum. Linters in general do not detect type errors that compilers catch and that prevent the program from running. A compiler is a bigger, better safety net than a linter.
I have ~25 years experience with many linters and many compilers, and my opinion is that compilers provide more security than linters, on the whole. When I can, I try to use a real compiler for production use of scripting languages, for example Google's closure compiler in JavaScript rather than linters like eslint or jslint.
> it's not an either or situation, use a linter on top of the compiler.
This is true, and I agree completely, it's not an either-or situation. That's in part what I was trying to say. The compiler already does linting and it does much better static analysis, so you don't need to choose, you can just use a compiler. There are certainly higher level style analyzers, clang-tidy was mentioned already, and there are others.
PEP-8, and Rubocop are in part a set of guidelines designed to prevent code mistakes and type errors precisely because the languages they represent don't come with a static type-checking compiler. Many of the linting rules and best practices only exist to prevent unsafe code that would have been prevented if there was a compiler involved, and only need preventing via style guides and linters because a compiler is not necessarily there.
There are certainly best social practices that some linters enforce that many compilers don't, but for that it doesn't make any sense to avoid learning C++. The OP's comment - that he feels like C++ is a minefield without a linter - is missing the forest. It is easier to know you're writing correct C++ than it is to know you're doing correct Python, because of C++'s compiler. Unfortunately no compilers or linters are that good at preventing you from writing code that runs and then crashes.
I'm considering linters as something you use in addition to compilers. Yes, they enforce fewer checks, but the assumption when running a linter is that the code compiles, already. Or, at least, that's what the assumption should be.
> This is true, and I agree completely, it's not an either-or situation.
Ah, okay. Yeah my issue was mostly with the either-or framing here.
> because the languages they represent don't come with a static type-checking compiler.
Yes, but this thread is about C++, which is a different world.
-Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wextra -Wformat=2 -Wimplicit-atomic-properties -Wmissing-declarations -Wno-long-long -Wnon-virtual-dtor -Woverlength-strings -Woverloaded-virtual -Wredundant-decls -Wreorder -Wswitch-default -Wunused-variable -Wwrite-strings -Wno-variadic-macros -Wno-unused-local-typedef -Wno-language-extension-token -fstrict-aliasing
and optionally: -Wconversion -Wdocumentation -Wfloat-equal -Wmissing-prototypes -Wold-style-cast -Wunreachable-code
and this is still insufficient. Why? Because this is only checking syntactical and semantic correctness. It can't check for violation of local policy, such as:no use of new/delete (use make_unique or make_shared)
correct and consistent use of virtual inheritance across the entire codebase
rule of three and rule of five usage
etc.
These are mostly higher-level concerns. Stuff which other people on my team might introduce, and/or miss in review.
I don't yet have anything automated in place for this, but clang-tidy is on my todo list for investigation.
Have you used any linters? Because linters are even worse than what you're describing with the C++ compiler. What they do is complain about style issues that some people believe are likely to lead to syntactical and semantic errors, without actually checking for the syntactical and semantic errors like a compiler does. Linters also don't check for violation of local policy, unless you extend them yourself. (And feel free to extend clang's warnings to suit your needs... it is open source.)
I fully 100% completely agree that C++ tooling could be way better, and I wish it was too. But that's not the issue we're talking about here at all.
Until of one the more secure alternatives gets more mainstream adoption, thus starting to be requested by our customers, C++ is going to be the tool to go to, when I need to step out of JVM and .NET languages to something more low level.
Something that could be enforced by all the compilers.
Many of the suggestions are supported in VC++ and clang-tidy.
Other commercial vendors are slowly adopting them on their linters.
Strangely, gcc seems absent from this effort.
So "std::byte" is not a character ("std::char") nor arithmetic ("std::int8_t/uint8_t"), but allows bitwise operations. It was really necessary? Anyone knows if that type allows defining the byte size in bits per instance?
std::byte still seems pretty useless, though. There already is a built-in type for designating bytes: unsigned char.
(http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0298r3....)
Motivation and Scope:
Many programs require byte-oriented access to memory. Today, such programs must use either the char, signed char, or unsigned char types for this purpose. However, these types perform a “triple duty”. Not only are they used for byte addressing, but also as arithmetic types, and as character types. This multiplicity of roles opens the door for programmer error – such as accidentally performing arithmetic on memory that should be treated as a byte value – and confusion for both programmers and tools.
Having a distinct byte type improves type-safety, by distinguishing byte-oriented access to memory from accessing memory as a character or integral value. It improves readability. Having the type would also make the intent of code clearer to readers (as well as tooling for understanding and transforming programs). It increases type-safety by removing ambiguities in expression of programmer’s intent, thereby increasing the accuracy of analysis tools.
My reaction to that can be summed up succinctly as "WTF!?" The whole point of uint8_t or (signed/unsigned) char is an 8-bit quantity that you can do arithmetic and bitwise operations on. To put it more bluntly, "have C++ programmers forgotten how computers work?"
The proposed solution is to add yet another same-yet-subtly-different type, with its own set of same-yet-subtly-different rules? If anything that would cause even more confusion due to the complexity it causes in interactions with all the other parts of the language.
IMHO this "let's do everything we can to stop people from even the very slightest change of possibly doing something wrong" line of thinking is ultimately unproductive... and actually rather dystopian. The end-result is quite scary to contemplate.
(The fact that an 11-page, text-only PDF somehow turns out to be over 800KB is somewhat less disturbing, but still notable.)
That's not a purely hypothetical point; I already create custom types to do this. Not every 8-bit type is a character, nor is it necessarily an integer. I always found it frustrating that the default stream output was a character when using numerical quantities; now we can specialise raw output accordingly.
The coroutines, ranges and concepts TSs alone are making C++20 pretty interesting, and some of the features will be available in compilers before 2020.
They did much of the work needed to get modules, concepts, ranges, reflection, parallelism, etc ready to go, but this snapshot doesn't include them.
Nonetheless, many of those features will be finished soon and may be available by compilers before c++20
> GitHut is an attempt to visualize and explore the complexity of the universe of programming languages used across the repositories hosted on GitHub.
> Github is the largest code host in the world, with 3.4 million users. It's the place where the open-source development community offers access to most of its projects. By analyzing how languages are used in GitHub it is possible to understand the popularity of programming languages among developers and also to discover the unique characteristics of each language.
"... Let's see Rust for what it is: the latest attempt at a C++ replacement. These have come and gone over the years, and it's by no means clear that Rust will succeed. As an example, Rust is currently 43rd of the 50 languages monitored in the Tiobe index. For comparison with languages of a similar vintage, Swift and Go are 10th and 17th respectively. C++ is 3rd. To put it bluntly: almost nobody is using Rust in the real world yet.
So please, ease up on the hype, Rust users. Have a little humility. You've got a nice little language with some really good ideas, and having a static analyser built into your compiler is cool. But there's a long way to go yet."[1]
[1] https://www.reddit.com/r/cpp/comments/611811/have_you_used_r...
I think some people define systems programming as "interacting with the OS all the time"; which is something that Go is really good at.
C++ = 22.3%
C = 19%
Swift = 6.5%
Go = 4.3%
Rust is not even on the list which means it's usage is less than 1.8%.
However, I think that post from Reddit was a bit misleading in its own way. Go has been much more mature from the beginning, given its authors and origins, and in some ways had an easier target, in being a slower but simpler, safer version of C, or a faster version of Python (as far as new users of the language are concerned). It's also in many ways sort of a modern version of C, so very familiar to potential users. Finally, it had its 1.0 release in 2012.
Rust, in contrast, had less of a head start. It is newer in a lot of ways in terms of its characteristics and features, and had a more difficult target, at the lower level and with the performance characteristics of C++. Finally, its 1.0 release wasn't until [less than] 2 years ago, in 2015. Go has been post-1.0 for over twice as long as Rust, which is a significant length of time in IT.
Golang might be #4 or so; there might be some projects that use Rust but not much; the raw C that comes to mind is from third party libraries like libpcap.
In case you're curious, a lot of our internal tooling for monitoring (to provide an example) uses Python.
https://stackoverflow.com/insights/survey/2017/
This isn't exactly what you are looking for, but I think it still shows that C++ is fairly popular. C is second among systems languages at 19% and Go is near 4% (Rust is presumably less than 1.8% since it's not even on the list)
I believe that Rust has the power to take a significant part of C++ in coming years. Maybe that also Ada will increase due to the rise of public interest in code safety. C will remain as it is because there is no easier way to port system software to new platforms.
PS. Please don't forget to show some love for C2x now. :D
The security annex is worthless, as pointers and lengths are still used separately.
Clang [1] needs a couple more things.
MSVC [2] hasn't done as much, but shouldn't be too far away. [3].
Considering how long C++11 took before it was fully implemented, this seems so fast!
[0] https://gcc.gnu.org/projects/cxx-status.html#cxx1z
[1] http://clang.llvm.org/cxx_status.html
[2] https://msdn.microsoft.com/en-us/library/hh567368.aspx
[3] https://blogs.msdn.microsoft.com/vcblog/2016/01/22/vs-2015-u...
*Old but close to metal and fast and versatile.
And by making library code easier to write, understand, and maintain, we make it more likely that the more obvious features (like filesystem operations, database abstraction layers, new kinds of data structures, etc.) can be written and maintained.
All that being said, there are completely unecessary warts in C++ that need to be cleaned up. The best thing in-the-trenches C++ developers can do to help with this is to improve the software development lifecycle tooling and practices on the projects they are responsible for. Good automation, static analysis, and testing will make the C++ community more agile and more ready to do the much harder work of deprecating and deleting old technical debt. And it's good for the health of the project anyway.
...despite claim that the light truck is a general purpose vehicle...people would chose for a new vehicle a bicycle, car, aircraft, motorcycle, or tank...
Use the right tools for the job. C++ is intended to be a general purpose systems programming language. An excellent tool for a wide variety of tasks, but not the be all and end all.
I am right now working on a library built in C++ and although I also have written some utility programs for the system in C++, its main interface is intended to be through (swig-enabled) Python and Common Lisp.
I wrote C++98/03 for years and kind of hated it. I love C++11/14. I've tried Rust and other languages, but C++ is such a good choice these days.
I agree that C++11 was a leap (older C++ was terrible). However, both C++14 and C++17 are just a sets of smaller or bigger improvements.
One of the reasons I found some pleasure writing Java instead of C++, even before it got a JIT, was the portability story.
Writing portable C++ code across the many commercial compilers available back in the days when the only standard was the C++ARM book, wasn't particularly fun.
So it might not be popular, but any alternative, currently, means more work due to FFI layers, less tooling support regarding IDEs and debugging infrastructure.
We should support those more modern alternatives, however also be realistic that only in the last five years or so, many companies have started to move from C into C++ (e.g. BMW, Sony,...), and they will take a few decades to switch to something else.
I am glad I do not have to deal with C++, for the very reasons you mention, but as far as I can tell, it is fairly popular already.
C++ is still popular because there are a lot of existing projects; nobody would throw away their products. Many things were standardized too late, like threads or strings. Lack of standard solutions had led to produce custom ones, often proprietary. Nobody would rewrite working-for-years subsystem just because C++ finally learnt what a thread is. Another example is variety of incompatible build systems; I wish C++ had something similar to PyPi or CPAN (I even don't dream about Go-like import system). Not to mention incompatible compilers, but I must admit there is a progress.
C++ has many substantial problems and when I see that the committee wasting time on such unimportant things, like a 2D graphics library, it makes me upset.
The goal is not to replace SDL, rather provide a portable way of doing basic 2D graphics.
The C culture of leaving the libraries to the OS was one of the reasons why C++ got a chaos of interoperability issues, letting other languages that understood how that is relevant to gain mindshare in the late 90's.
C++ needs its batteries.
The truth is that it just wouldn't otherwise get done. Maybe twenty years from now there will be committees working on separate modules and we'll download those if desired.
So lets remove stdio and iostreams from the standard, shall we?! Just for the sake of keeping the standard pure.
A language goes hand in hand with its libraries, failure to understand that just leads to oblivion.
One of the reasons C++ has done so well is that it sticks to its area of competence and doesn't try to do everything for you.
C++ is almost gone from the GUI space, that is how well it has done.
The GUIs from desktop and mobile OSes have moved into other languages, leaving C++'s the role of just talking to the GPU and little else.
In addition to the obvious performance improvements this would give compilers, this really cuts down on the complexity that third-party tools need to deal with to work well with C++ code. The quality of tooling for C++ has historically been stymied by the complexity of analyzing the code itself. Modules are a huge step in the right direction for helping with this.
$ echo "#include <iostream>" > foo.cpp
$ g++ -E foo.cpp | wc
37799 104779 1280834
Including just iostream in a file means the compiler has to process 37799 (!) lines.For comparison, a C file including stdio:
$ echo "#include <stdio.h>" | gcc -E - | wc
456 1638 20880
That still looks bloated to me, but is about 60x times fewer bytes. $ curl https://git.musl-libc.org/cgit/musl/plain/include/stdio.h | wc
203 630 5231Second, C++ is popular by pretty much every measure I could think of. Whether you want to measure lines of code, or number of projects, or number of developers - it is very high on the list.
It is true that is not popular with web developers and gets shouted down in those echo chambers, but the web entirely runs on C++ because all browsers are written in C++.
Of course, I can install any compiler, but my employer might not allow me to use it. Porting to a new compiler is not an easy task when a code base is large; we postponed porting due to lack of time.
> Second, C++ is popular by pretty much every measure I could think of. Whether you want to measure lines of code, or number of projects, or number of developers - it is very high on the list.
More interesting measure would be the number of new projects.
> It is true that is not popular with web developers and gets shouted down in those echo chambers, but the web entirely runs on C++ because all browsers are written in C++.
In web backend C++ is not used. You find there C#, Java, PHP, Python, maybe Go.
Every now and then, I integrate a native library into our Java and .NET projects.
A significant amount of code for Google/Amazon is Java and Microsoft uses C# for a lot of infrastructure.
Not entirely true - Firefox is rewriting some components in Rust. They already included the first Rust code in Firefox 48, and Firefox 53 will require Rust to compile.
[0]: https://gist.github.com/mattico/a5e5f9d58a3991d0e3e844e97fa0...
That is, preliminary WebRender has landed, but is being done incrementally, so the gains aren't big yet due to some copying that won't be necessary in the long run.
You're totally right that it's just a start. This stuff takes time!