Congratulations to everyone involved, pity we still haven't got concepts and modules into it, but there is still hope for the next round. :)
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.
Is there an overview of what kind of challenges prevent the inclusion of modules? I don't do much C++ anymore, but I've done a fair bit of work on module systems, and they've never seemed that complicated to me. (I worry that the answer will mention the preprocessor...)
My utopic dream for C2x would be official data structures for safe arrays and strings, alongside some standard way to enable bounds checking on processors like Intel and Sparc ones.
The security annex is worthless, as pointers and lengths are still used separately.
It's too late for C++ to regain popularity. C++17 features will become widespread in next 3-4 years (C++14 isn't a common standard yet). Moreover, the language has become incredibly complicated and sadly doesn't provide anything that would reflect modern needs.
Regain popularity? It never lost popularity in the areas it was a good fit for. It's still a great fit for certain kinds of code that requires high performance or low overhead.
I meant that despite the claim that C++ is a general purpose language, it is not popular among average developers. People would choose for a new project C#, Java, Go, Python, Scala or Javascript, but not C++.
> I meant that despite the claim that C++ is a general purpose language, it is not popular among average developers. People would choose for a new project C#, Java, Go, Python, Scala or Javascript, but not C++.
...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.
You know C++, you're not an average programmer. Entry level into the C++ world is too high for a regular programmer, they would choose something easier. That's the point.
We compile our product with GCC, Clang and MSVC, and we need some #ifdefs. MSVC for years was far behind GCC/Clang, recently Microsoft did a really good job and they catching up. But some #ifdefs are still needed. :)
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.
I have never understood this stance 'C++ was terrible'. Even with the introduction of destructors - and exceptions! - C++ became way ahead of other languages of its time and almost instantly secured its well deserved place in the minds of programmers.
OK, maybe "terrible" is too strong adjective. What about "cumbersome"? :) C++11 allowed to get rid off many silly workarounds and introduced, among many others, threads and rvalues.
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.
It is still the official Infrastructure language on the SDKs in OS X and its variants (IO Kit, Metal shaders, LLVM), Android (NDK, ART implementation, LLVM), Windows (DX, UDK, UWP, C++/CLI, C++/CX), Game engines (Unreal, Unity, CryEngine, Godot).
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 not a fan of C++, believe me, but I as far as I can tell C++ is quite popular in the sense that it is used a lot - all major web browsers are written in C++, for video games it is the language of choice, both Windows' and macOS' kernels are written in (a subset of) C++, lots of desktop applications are written in C++, and that is just the stuff I happen to know.
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 my bread and butter. I neither hate or love the language, just use it and observe the way it is evolving.
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.
A 2D library is important, back in the day all C++ compilers on home computers had one.
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.
I understand the purity of this statement. I even wish it could be true. But without a standard library shipping with the language itself (today's approach to things) then who is going to implement this standardized IO addon that a whole lot of us need?
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.
If you're referring to Borland's BGI interface, it was god-awful. Had it become a standardized library, it would have set graphics programming back decades.
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.
I am curious, what would having modules give us that we could not have with classes and namespaces? (I understand that in a language like Java a module, a class, an interface - are all different things. C++ is different in this respect, as it only provides a mechanism and not a policy.)
The main appeal for me is the possibility for substantially decreasing compile times. The current include system really precludes a lot of work in this area.
#include is literally expanded to the contents of the file you are including. And that works recursively until the compiler has one giant source file that recursively includes the text in all the headers you included. And in that process all preprocessor macros are also expanded. This happens for every source file that is compiled. It would be nice to skip all that and just have some standard way of listing the already-analyzed contents of a the modules you need.
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.
First, all the compilers already implement pretty much all of it. I'm not sure if by widespread you mean "included in a distribution" but you can use these features today, if you want to install a compiler.
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.
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++.
> First, all the compilers already implement pretty much all of it. I'm not sure if by widespread you mean "included in a distribution" but you can use these features today, if you want to install a compiler.
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.
If you have to "port" your code from one C++ compiler to a new C++ compiler, then they are not both true C++ compilers per standards, or your code is not pure standard C++.
Sometimes compilers have bugs or are not fully-compliant. For example MSVC two or three versions ago didn't understand =delete. Standard library also might have errors. Moreover, we use third-part libs that are not always up to date (for various reasons), we have some legacy parts, and so on and so forth. I wish switching compiler required only setting another CXX. :)
Except at Google, Microsoft and Amazon. As far as I know the three biggest public clouds are all implemented with C++ as one of if not the primary backend language.
>the web entirely runs on C++ because all browsers are written in C++.
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.
It's absolutely valid to say Firefox is written in C++. It has 3.7 million lines of C++ and 67,000 lines of Rust [0]. Even if Mozilla uses Rust for everything, it'll take much more than that for it to come anywhere near the popularity of C++. I say this as a Rust aficionado.
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!
That SO question has barely any code examples but mostly links to sometimes quite technical documents. I'd really love to see a comprehensive list of all features (if possible c++11, 14 and 17) together with small explanation + code samples: even though I am already using a lot of the new features I still feel like I'm missing out on certain things just because I don't know they exist and because the information is shattered. (e.g. I'm fairly sure SO has Q&A on like every new feature, but it would take an insane amount of time to go through every question tagged [c++17]).
I don't know if similar things existed for C++11/14. But, it doesn't exist for C++17.
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.
cppreference.com usually has [c++XYZ] marks on features introduced by a specific version of C++ and it is usually current with updates while having some basic examples for most things. The site doesn't have a comprehensive list of all the features introduced in the specific version of C++, but which ever feature is interesting to you should be easy to find there.
In modern gcc, std::variant doesn't look like a competent replacement for old-fashioned tagged unions.
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):
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.
Eh, I get that one of the points of C++ is to minimize abstraction penalty even when you do use abstractions, but these things are compromises. In almost all real-world software development the advantages of abstraction far outweigh micro-optimizations that shave off individual cycles...
Writing ad-hoc tagged unions and two-element 'optional' structs is a completely straightforward mechanical task---exactly the sort of thing that a programming language ought to automate. Why does there need to be a "compromise" between boilerplate and performance here? Why should I have to pay performance to use standard tagged unions and optionals, or conversely, pay by writing boilerplate in order to get performance?
If the individual cycles don't matter, you can use a safer language than C++ which compiles faster and provides more static and dynamic guarantees. If you choose C++ for a new project in 2017 it's because you need all the cycles and would have chosen assembly if you thought you could write the asm fast and cheaply enough.
First of all, the world isn't that black and white. Second, the advantage of C++ is that you are not forced to use these abstractions. You can pick and choose when to use them and pay the performance penalty.
For the parts of the codebase where you can use abstractions that have runtime costs, you can also choose a safer language that imposes similar runtime costs. I bet it would be easier to write maintainable code in the safer language than in the version+subset of C++ on which your team agrees.
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.
"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.
Many other languages have industrial support, a proven toolchain, and are known by a lot of candidates: Java, C#, modern C... this is if we restrict ourselves to only the most popular languages with compile-time type enforcement, which is fairly arbitrary.
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.
Yes, there are many alternatives. None of which offer the same advantages as C++.
If one can swallow the costs, by all means, be my guest and use whatever language you want, no one will care much, unless you end up using 13% CPU rendering a blinking cursor.
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.
It would really depend on what the project is (3d shooter game vs database server vs high frequency trading). But I think many projects can be broken into two parts:
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).
You started with an absolute statement "C++ should not be used in 2017 for new projects" and in the following comments slowly but surely admit that the above statement is false.
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.
You are putting words in my mouth. I did not say "should not be used". I wrote about my option and what I do. I did not mean this advice applies to everyone in every situation.
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.
Your whole argument falls apart when one considers that performance needs aren't split just between SIMD + careful data layout and anything goes.
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.
And the disadvantage is that you have to pick and choose them after learning about all of them, and you have to deal with the choices made by whatever other code you have to work with, and you have to reason about all the combinations. For most tasks, this is overkill, which is why C and languages other than C++ persist even though C++ has everything.
I've seen this kind of misconception before and it should be corrected. Your premise is wrong, there are other reasons to pick C++ besides performance:
* 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
Another cool feature, on top of steveklabnik's comment: rustc is actually smart enough to collapse `Option<T>` where `T` is a borrowed reference (pointer) to a single word. Basically, the compiler knows that the pointer can never be null (borrows are always valid when in scope), so it can use the non-null values for `Some(...)` and the null value for `None`.
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.)
std::optional is nice if you have a class with invariants that you want to always maintain (i.e., you don't want to deal with the pesky "uninitialized" state). You can build a class that always requires proper parameter in its constructor, and then you apply optional<> only when you defer initialization.
In most cases, I imagine the performance penalty would be dwarfed by the cost of actually using the class.
I suspect the issue is that variant<int,char> is not trivially copy constructible (at least when I tested on godbolt), so the ABI believes it is not allowed to pass the object by value. (this is a guess only, correct me if you know better!)
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
Unfortunately the abi requires non-trivially copyable/destructible types to be passed by (hidden) reference.
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.
"Perhaps the most exciting thing was that we decided to add the std::byte type"
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?
This is analogous to adding uint8_t when we already had unsigned char. In C these would be exactly the same; in C++ they are different types. Same with uint8_t vs. byte: the former is an integer type, the latter is not. (Thus, a better question would be, why introduce byte when we already had unsigned char. I think, the answer to that is in a general tendency of moving away from the C way of looking at types and making code better reflect the intent and do it in a more type-safe manner.)
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.
such as accidentally performing arithmetic on memory that should be treated as a byte value
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.)
Overloading and templates. I can now use unsigned char, uint8_t and byte as distinct types, meaning they can be separately overloaded and used as separate template specialisations.
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.
As a matter of personal taste, I prefer big complex languages over simple ones
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++
The history of computing is full of programming languages that started as a cry against complexy, only to discover that complexity has a reason to be and then they either adapted, becoming themselves as complex as their enemy, or faded out of the computing scene.
Nothing against personal preferences, but one side-effect of overwhelming complexity is that only very few people can be trusted to write safe C++. The better you know C++ the more suspicious you become of C++ code written by others. At least that is my personal experience.
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.
This is not as bad as it sounds. You need to consider the absolute numbers than the relative percentages for languages like C++.
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.
>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.
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.
C++ has been getting a lot safer though. Modern C++ generally has you using shared_ptr and unique_ptr and references, which cut down on a lot of common pointer mistakes. There's also a lot of const mixed in, which I think helps. Debuggers have also gotten a lot more reliable (I remember one crash bug that I couldn't find after like three days of looking in an old visual studio version, whereas newer visual studio caught it immediately). Not that the language isn't a minefield, but if you walk in the modern part there's a lot less mines buried in the ground.
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.
> I somewhat reject the notion that writing performant code is a niche thing.
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.
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.
This was not Ada's fault but the developer team's fault since it used a working Ariane 4 software for Ariane 5 without exhaustive testing. They made the mistake, and blamed Ada for that. The Ada software worked perfectly for which it was written for.
Crashes due to the language implementation's fault are much more likely in C++ than in Ada. Ada compilers are 100% verified, otherwise they are not allowed to call themselves "Ada compiler". There is no such thing for C++. The safety gap between C++ and Ada is actually so big that we don't even need to talk about that.
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."
Complexity in a programming language is fine if it is just you, but a group of developers working together with different ideas of what to use can make for cacophony.
it means you can ignore some the complexity .. until you want it, or need it
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.
And since they don't have access to said features you get some crazy framework libraries as poor man's replacement for language features, like doing OOP in Motif, all those byte code manipulation and aspect oriented libraries in Java or now the pile of code generation tools in Go.
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.
>""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"
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?
The C++ Core Guidelines[0] specify — albeit kinda verbosely — how to write modern C++. Implementation support to enforce these guidelines is ongoing, but MSVC and clang-tidy offer some support.
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.
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.
Dumb question: How popular is C++ as a systems programming language in 2017? Does anyone have data on the popularity of various languages (C, Rust, Go, etc.) when web and application development are excluded?
> 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.
C and C++ are the most popular "systems programming languages", C is king in embedded, kernels, C++ is a king in everything else. Go is not strictly "systems programming language", as to Rust popularity this is the most pragmatic answer I've seen lately:
"... 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]
i recall there being some whining over go and "systems programming", but this seemed to hinge on definitions. go may not be the right option for a kernel but it's great for servers, infrastructure, platforms and various related things.
Systems programming is a vague term but it usually refers to low latency software (e.g. kernels, browsers, OS's, embedded, databases, etc) which means anything with a garbage collector is out of the question.
Systems programming is all about control. That usually means being able to control which instructions are emitted by the compiler and being able to control how things are laid out in memory, but it also means being able to control what happens when; and Go doesn't let you do that. If you can't guarantee that the function that's supposed to turn the reactor of when the temperature is too high finishes in time then that's a deal breaker.
I think some people define systems programming as "interacting with the OS all the time"; which is something that Go is really good at.
I have nothing against C++, Rust, or Go--I like all of them for different reasons and see them serving different goals, and see room for all sorts of languages. I also agree that there's a discrepancy between how Rust is discussed and how it is used, and don't see C++ going anywhere for a long time.
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.
It's among the top 3 non-web languages at Google (with Java and Python (?); I don't remember the current rankings, but I think C++ used to be #1 but has now been surpassed by Java).
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.
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)
C++ and C will still remain alive for a long time. C++ for reason of legacy code in business, and C for its unique feature of being the standard "high level assembler". There is always at least a C compiler available for every new platform.
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.
This is one of the nicer things one could say about C++. Indeed, it is possible now to write C++ almost as if it was Java and still produce a reasonably efficient code!
Care to explain? Aside from garbage collection, C++ has basically always had all Java language features. If anything, I would argue that C++ is mostly a superset of Java, since it includes strictly more -- for example, much better support for type-generic programming.
My rule of thumb : never optimize your code, instead optimize your algorithm as much as you can. After you finish, you can profile your code to see where you made mistake.
Algorithm optimizations can be far less readable than other kinds.
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.
> Most C++ compilers have them, the problem is the macho coders that think that know best.
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:
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.
Why disable tautological-compare? Of all the pickier warnings over the years, anecdotally I'd say it's been one that's caught an outsized number of actual bugs.
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.)
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.
I take the alternate approach to this, which is to let the compiler warnings (and other related tooling, like static analyzers) drive how I write the details of my code. I think it leads to a higher average code quality than the micromanagement approach where the details need to be perfect. In particular, as soon as you have multiple contributors, people tend to have inconsistencies in how they prefer doing things. Having some tooling enforcing all this really helps in killing unproductive arguments :)
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.
Right, yes. I guess a 4-value enum could be an option too, but I've never tried.
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.
EDIT: 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.
Yeah, C++ has that. Other languages - Ada and Rust for instance - don't need that. If you are concerned about code safety then C++ is not a good choice.
Yeah, I kind of agree that C++, when used badly, can result in some serious mess-ups in the safety department. But for better or worse the language is here to stay (at least for the foreseeable future) so it's good that these guidelines and tools exist.
?? Compilers do reject code that doesn't meet a certain standard. C++ does come with a "linter". You might want to check out what -Wall does in gcc & clang.
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.
> Compilers do reject code that doesn't meet a certain standard.
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.
> What a compiler enforces is not best practice, it is bare minimum.
-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.
> If a compiler enforces bare minimum, then a linter enforces less than bare minimum.
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.
True true, and this sub-thread is specifically about someone who is afraid to use c++ due to lack of a linter. I've used c++ for the majority of my career, and all I really wanted to say to @codebeaker is don't be afraid to learn c++ for lack of a linter, because it comes with one. My mistake that I framed it in an argumentative way, that ultimately wasn't my intent.
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.
So, then you feel that @codebeaker should wait to learn C++ until tools that fulfill your wishlist are available? You agree that C++ is a minefield compared to Ruby, only because Ruby has Rubocop and C++ doesn't?
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.
I'm just glad to see languages as old* as C++ evolve and continue to have improvements made. It's a good time to be a programmer: our tools just keep getting better.
Still no concepts unfortunately (or reflection). Bit disappointed really, I'm far from a guru but to me this seems like another 'tick' upgrade where c++11 was a big 'tock', c++14 was mostly polish to c++11.
Eight years passed between C++03 and C++11, so I think it's okay to have nine years before the next big release---but with two iterations of polishing in between.
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.
If you don't think of it as building a specific version and more just as a snapshot of what is currently 100% ready-to-go, you'll maybe feel differently.
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
I share this desire, but it's important for end-users to remember that even if a feature seems arcane and unneeded, you're likely using it indirectly through the libraries you use. Take variadic template parameters for example. The average developer doesn't use these. But very popular library features like make_shared would be at least an order of magnitude more code.
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.
If that's all you want, you might take a look at the `cleanup` attribute for C. It's non-standard, but it is supported by `gcc` and `clang` and is fairly effective.
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?
180 comments
[ 2.9 ms ] story [ 234 ms ] threadUntil 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.
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...
...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.
For comparison, a C file including stdio:
That still looks bloated to me, but is about 60x times fewer bytes.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.
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!
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):
as compared with calling f2(42): 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
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
vs 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.
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.
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.
http://www.ada2012.org
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...
Avoidable complexity is the root of all evil.
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.
> 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.
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.
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.
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:
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:
Looks nicer than: 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.)
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.
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:
Pop header:EDIT: 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.
[1]. http://clang.llvm.org/extra/clang-tidy/
[2]. https://github.com/isocpp/CppCoreGuidelines
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.
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.
*Old but close to metal and fast and versatile.
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
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.
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...