Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
C++ confessions of a C developer (undo.io)
141 points by wyldfire on Dec 3, 2016 | hide | past | favorite | 84 comments


People criticising C++ always sound to me like the language somehow leads them into abusing it.

People mess up when coding in C++, not the other way round. Blaming the tools and seeking restrictions to one's freedom of expression in using them, won't have my sympathy. At one shop I once worked, they have added all sorts of protections to all tools they used, in order to prevent developers from doing wrong. For example, in the source configuration management, they disabled branching and parallel development, someone considered that too complicated. And Make and its language was completely hidden, of course.

I personally greatly value C++ for the expressive power it gives, compared to straight C -- not only solve the problem but express the algorithm the way that a random person reading the code instantly grasps the idea, etc. I find it harder to achieve using straight C, on average. (I am in low-level and performance-related development, choice is frequently only between the two.)


The bigger the team the more restrictions you want in a language.

C++ is lovely when you are working alone, but as the team grows people start having very conflicting opinions on what parts of the language should be used. The only way to handle this is to restrict everyone to a subset of C++ and forbid everything else, otherwise it will be impossible to navigate the codebase.

Innocent looking things like try/catch becomes a nightmare when not everyone has taken that into consideration when they clean up resources. Either you have to enforce proper cleanup around every function call or you have to forbid everyone from throwing exceptions, there is no middle ground here.


Does anyone know everything about Python 3.5, language and libraries, including evolution issues when having to handle old code?

What about style guides to forbid people to use generators, metaclasses or other advanced features?

Just to pick a language most people think it is easier than C++.


Are generators really an advanced feature? I've used them pretty often (instead of returning a list) and they're pretty simple.


For many types of programmers that would be happy with something like C or Go, most likely yes, given that they already allow for some interesting patterns. Also because they changed a bit, in the early days you could not pass arguments back to them.

However, when I wrote generators I was actually thinking about comprehensions.


I think comprehensions are less advanced (they're a specialized case of iterators) and very commonly used.

> Also because they changed a bit, in the early days you could not pass arguments back to them.

Sending arguments is certainly advanced.


I agree that the problematic of big teams of heterogeneous skills is not the same as the small teams of skilled people (some fields simply won't tolerate anything else), but the rest of your message stills sounds the same to me -- somehow the __language__ needs to be "restricted" because some (few?) __people__ on the team abused it?


There is nothing specifically wrong with C++ en toto. What's happened is that historically, it was perceived as a leverage tool to make larger, more ambitious projects attainable. What I saw of that was that the failure rate went up.

So my memory is that C++ is mildly "worse is better" than was C.

I think the failure rate went up because:

   - more people got drawn into programming. Some of them 
     got dumped there; many people with whom I worked were 
     actually, say aeronautical engineers who were told 
     that they had to pivot to software to keep their job. 

   - people think of the radius of software when thinking
     of size, when the real measure is the surface area 
     of a sphere implied by that radius.

   - Us old guys got to learn C on smaller projects which 
     were actually deployed, so we had the benefit of 
     going through the full cycle, playing all the roles.

   - You can easily run into ctors/dtors problems when
     decomposing C++ projects into modules. 

   - Preventing integration problems between modules just
     requires a lot of good interpersonal communications 
     and sometimes, C++ gets in the way. 

   and most insidious of all

   - New language systems are devilishly hard to embrace in
     environments which are intended to be competitive. 
One thing I've learned is - expressive power is 100% about what the expectations of the reader are. I find differential equations more expressive than English for those things where they are appropriate, but that's because I trod a different path. With C++, the expressive power is because the reader unpacks more information per symbol-suite. Just realize that that is not the same for everyone.


> With C++, the expressive power is because the reader unpacks more information per symbol-suite. Just realize that that is not the same for everyone.

Then reducing the expressive power of a language will only make this worse, not better. To make code to speak to a random reader, one needs to carefully select idioms (from the professional domain, not the language's ones) he/she wants to implements, and if new/unfamiliar ones need to be introduced, make sure they are clean and easy to grasp. Removing features from the language makes this harder.

Funnily enough, people frequently illustrate their point with exceptions, whereas in my league of a single feature contributing the most to code readability, exceptions compete for #1 position! They are easy to grasp __conceptually__ for a C programmer, and when properly used, make code much easier to read. They also create a feeling of confidence when dealing with code (as they cannot be missed, contrary to error signalling via return values). Etc.


I would not consider exceptions a significant improvement in C, in general. I might make allowance for using them for division, signed integer math where overflow is a possibility or in cases for memory overwrite when possible.

IMO, exceptions ( and I use them A Heck Of A Lot, probably to a fault in coding Tcl ) are really just a convoluted control flow mechanism, and I'd rather see the expectations made explicit than exceptional.

Heck, with full-on MMU memory protection, all code that's not in kernel mode should be free of memory overwrites anwyay. I say that as a maintainer.


Agreed. I've always shaken my head at people who essentially say "______ is terrible because it makes it easy to shoot yourself in the foot."

The proper answer is to not shoot yourself in the foot.

Most of my programming is done in Python, where people cry about the inability to create private class members. IMO, use the convention of prefixing the name with an underscore, and if a user of your module messes with something marked as private, then it's on them when their program explodes. Don't blame Python for not supporting private members.


> The proper answer is to not shoot yourself in the foot.

That's a bit like shrugging your shoulders when an infant walks off a precipice and saying the proper solution is for the infant not to walk off the precipice. The proper solution is actually either to put up a rail, making the precipice safer, or keep the infant away from the precipice in the first place (or rather, to hold the infant by the hand whilst showing them the safe way to approach the edge so that they can go solo when ready).

Or to stick with the poor analogy, the reason people used to shoot themselves in the foot is because old guns could easily go off in the holster. The answer was the safety catch.

Back on topic, the only reason this is not done with C++ is because people have come to rely on the ability to shoot from the holster (often avoiding their foot) and the back compatibility dictates that the ability must therefore remain. There are plenty of features that would not have been designed that way if C++14 had come into the world fully formed without evolving via its ancestors. It's also one reason people keep inventing new languages - it's an opportunity to learn from past mistakes with a clean slate, not just to bring in concepts that simply don't fit.

I would argue that there is scope for picking a 'major version' of C++ and consciously breaking back-compatibility in some areas. It's controversial, because it would require a lot of work in some existing C++ projects if they wish to benefit from any new language features beyond that point. Just look at the hooha made around Python 3.


Incredible book (and reference) if you want to learn literally everything about C++ (and which parts to use, how and why): http://www.icce.rug.nl/documents/cplusplus/

It's continually updated (pdf available on GitHub).


Personally, unfortunately the more exposure I've had to the "Modern C++" community, the more I feel like it's dogmatic, cargo-cult, and obsessed with "best practices", which really puts me off. It looks like a manifestation of the second-system effect compared to C, which I'd characterise as a simple, pragmatic, and humble language. Then again, I've always thought OOP was oversold and that may have something to do with it.

That is not to say I fundamentally dislike the language itself; C++ certainly has some very useful features compared to C, and I sometimes wish I could make use of them when I'm writing C too, but the "C++ is so much better than C, C is bad" and all-too-common "some bloke named Herb says X, so you must follow him" sort of attitude coming from self-proclaimed "Modern C++" developers I find rather distasteful. I don't care about purity or adherence to any perceived "expert opinion", I just want to use the features of the language that make it easier and simpler to solve a problem more efficiently (and likewise, not use the features which don't help)... which is what programming languages ultimately are for, and yet I feel much of the "Modern C++" community has missed that point.


> I've always thought OOP was oversold and that may have something to do with it.

Almost all of the recent innovations in C++ focus on aspects other than OOP. I can't think very many new OOP languages features in C++11/14/17, except for `override` and `final`. All the new hotness is about functional programming and in some sense, generic programming, which, IMO, is the right direction.

> I just want to use the features of the language that make it easier and simpler to solve a problem more efficiently (and likewise, not use the features which don't help)... which is what programming languages ultimately are for, and yet I feel much of the "Modern C++" community has missed that point.

I feel that you are exactly the kind of person the author has described in the beginning of the article: a C++ sceptic, especially a "Modern C++" sceptic. The article even quotes Douglas Crockford in saying "some of those features were more trouble than they were worth." The article also quotes Bjarne Stroustrup saying "[w]ithin C++, there is a smaller and cleaner language struggling to get out." The "Modern C++" community that you have derided is exactly the community that knows not every feature in C++ is good, a community that tries to enshrine the tried and tested "good features" into "expert opinion" and "best practices" and then spread them through talks like this one.


Honest question: given you're saying this, do you know modern C++ in the first place? In other words, are you speaking with knowledge? Or without?


I suppose that you could just use C with std::vector and std::unique_ptr from C++, and you’d be much better off. The you could still write "C" code but not worry about memory leaks.

Of course, you also need std::sort because it is much faster than qsort. Thinking about it, you probably want to implement all time-critical algorithms with generics.

... never mind, this quickly becomes a stone soup.


I keep hearing that std::sort is faster than qsort yet when I benchmarked it with GCC it was the exact same performance which makes sense as modern compiles are either to optimize function calls through pointers. Anyway, both are significantly slower than macro based library based on removing function calls altogether (not the one in comparator but the recursive qsort calls).

For things I would like to use C for std::vector is not very useful either as it grows in some generic way which is likely wasteful for specific applications. If an algorithm is time-critical then almost by definition the generic implementation in standard library won't be enough.


So for std::vector you avoid the "generic way" and specify the size up front or when needed with reserve. Just as efficient as a realloc in C. Many things can be inefficient or wasteful, but vector allocation and resizing isn't one of them if you care to use it effectively.


The thing is, there isn't one std::sort, neither one C++ implementation.

Try that with ICC instead, for example.


> removing function calls altogether (not the one in comparator but the recursive qsort calls).

That's an impressive feat as quick sort is not tail recursive.

Edit: you can of course maintain the recursion stack by hand but that's not normally a win.


I am not sure why you think it's not normally a win. It is quite a big win in qsort implementation at least.


On the other hand, "inline" too much code which is faster when benchmarked in isolation, and thanks to cache effects you may end up with worse performance as now less code fits in the cache.


On the gripping hand, dead code elimination after constant and range propagation, might make the dynamic cache footprint the inline ed code smaller.


std::sort was about twice as fast (!!) last time I ran my benchmark.

I don't think std::sort would be slower than a macro based liberty.

Obviously, you can reserve memory in a vector in the beginning.

> If an algorithm is time-critical then almost by definition the generic implementation in standard library won't be enough.

I'm afraid I'll have to disagree here as well.


Reran the std::sort vs. qsort benchmark:

Visual Studio 2015: 1.79x

WSL gcc 6.2: 1.92x

WSL clang 3.8.0: 2.08x

Ubuntu 16.10 VM gcc 6.2: 1.68x

Ubuntu 16.10 VM clang 3.8.1: 1.89x

All in favor of std::sort.


Have you used most aggressive optimization settings? I am getting the same results on GCC 5.3 Mingw x64, Windows 7.


Standard CMake 'release' compiler settings. No -march etc. for GCC.


Exactly - it quickly becomes a stone soup.

The main use case of a code base that is of value to me is: Can someone quickly determine that they have added a defect when doing maintenance? There are a lot of solutions to that.


the "Modern C++" community

Could you describe what/who you think this is, because I don't really see a community as a whole for who the points you make are valid. Sure there's some crazy purists everywhere, but in general I don't think it's as bad as you mention. Then again might be biased because I write way more C++ than C.

I know cherry-picking isn't usually the most fair way to discuss, but some things really strike me as unfair so I can't help it.

obsessed with "best practices"

not sure if this is really bad? When pushed to the extreme it is, but that goes for anything extreme, but I don't really feel the C++ community is like that. At least I've read many times things in the spirit of 'best practices ar good, follwing them blindly is not'. Also anecdotally from all colleagues I ever worked with those with some healthy amount of (as in, still being able to think critically) obsession with trying to Do The Right Thing, always wrote better code than those who lacked that

OOP was oversold

it surely was, but imo one of the things modern C++ teaches us is exactly that: OOP overuse is bad and you don't have to use OOP at all in C++ if you don't want to

"some bloke named Herb says X, so you must follow him" sort of attitude

which is in turn countered by an attitude of questioning everything, no matter if the author is called Herb or Bjarne, and I don't think I'm dreaming that (at least I've seen many questions on SO starting with 'in xxx Herb says y, wtf is that all bout?'). On the other hand, those guys' advice is usually golden so following it won't hurt much, as long as you don't blindly follow it.

I just want to use the features of the language that make it easier and simpler to solve a problem more efficiently

in the end everybody wants this I guess, and I do have the feeling that when searching for questions to typical problems I usually do get an answer telling me exactly what to use. Also take https://github.com/isocpp/CppCoreGuidelines for example: sure theres a whole lot of info but it does give a ton of good/bad examples, plus reasoning behind it


I think this misses the point of what "Modern C++" is about. It's absolutely about best practices, and that's a good thing.

Go back to the mid '90s. There was a lot of awful C++ code out there, and a large part of that was the language was dangerous for many people who didn't know how to use it safely or effectively. Some of that legacy persists today in old codebases. The STL and the C++98 standard library improved upon that, but there were still dozens of interesting ways of shooting yourself in the foot.

Then we had people like Meyers who wrote whole books explaining the dangers and how to write code to avoid them. These were the best practices, and they are hugely helpful. I use them daily in my work, preventing subtle bugs, leaks, undefined behaviour and random crashes. These turned C++ into something which could be safe and effective to work with, provided you didn't ignore the guidelines and do anything irresponsible. C++11 and 14 improved upon them, and again Meyers brought out a book to explain a whole new set of pitfalls to be aware of.

I agree with your assertion that it's to some extent dogmatic. But I don't agree that it's cargo culting (though some people may be). Over the last 25 years, we've collectively learned that there are some things which you must never do (e.g. throwing exceptions in destructors), and some things which you should or must do. Like the rule of three or rule of five, RAII, or how to implement Java-style interfaces with virtual inheritance and various deleted operators and constructors. Experience has shown that this is the right way to do things, and you'd better have a good reason for deviating from that. Languages like Java benefit from being restrictive and only have one safe way to do things. That's not true for C++, where you can do what you like even if it will explode in your face, and having a set of best practices we all agree on make things safe and efficient to work with. Certainly on the team I work on, being able to refer people to Meyers and say: "this is the way to do it, and this is the rationale" is beneficial and educational to the people concerned, as they get a better understanding and appreciation of the language subtleties, rather than their work making the code segfault or do the wrong thing.

For the minority who are cargo culting, I'd rather that they followed the dogma and wrote safe code even if they don't fully understand the rationale for doing so, when the alternative is writing unsafe and buggy code. Unfortunately, there is a minority that doesn't care to understand, and for them a set of strictly enforced rules is required to avoid disaster.


After many years of writing a self confessed horrible mix of C/C++ and calling it C++ (and I think more people have done that), I decided to learn C++11 and then C++14. I am enjoying it quite a bit I must say... Anyone else have that experience?


I learned how to write "C++" in the early 00's when I was the maintainer of a half-assedly "converted" CircleMUD that more or less just used function overloading so the idiot--err, charming gentleman--from whom I inherited the codebase didn't have to remember the order of arguments for "send text to character".

I then didn't touch it for most of a decade and re-learned C++ essentially from scratch maybe...three years ago? C++11 from the jump, with slowly adding in C++14 stuff as it made sense. And I like it well enough. It's never going to be my first-choice language, but that's because the environment around C++ is a mess rather than the language itself. The language has stuff to know, but I find that most of it is stuff that is totally comprehensible given that I understand how C++ works--like, of course I need virtual dtors if I've got classes, because I understand vtables and the necessity for a lookup in one. It's complex, in that there are a ton of different components, but I don't find it complicated, in that any component is difficult to understand in isolation or that the interactions between components have particularly many gremlins. (Which isn't to say that I'm a particularly good C++ developer or anything, but I understand the land mines and how to be better at stuff I need to be better at when it matters.)

These days, I can't envision ever writing more C than is necessary to wrap C++ for use as a library in Ruby, etc.; life's too short to not have dtors.


I made a conscious choice to use some of the new stuff like unique_ptr (primarily) and shared_ptr for memory management w/ move, lambdas, range loops and forward for varargs functions that are not an unsafe macro mess, constexpr, static asserts. It was quite nice, some of that is due to compiler progress, i.e. I always run with address sanitizer now.

Sadly they seem to have added more than they cleaned up. It's 2016, I don't want to have to write another freaking include guard. That should have ended years ago. UTF8 and friends are also a consistent pain, mostly because 3rd party library support is absent. This requires a strong message from the standard library or it's always going to falter.


pragma once is supported by enough compilers to be considered a standard by now :)


I built guardonce[1] to help mitigate complaints that #pragma once was non-standard. If you can easily convert back to include guards, you can worry less about what compilers you might support in the future and just consider the compilers you support right now.

[1]: https://github.com/cgmb/guardonce


FWIW we had our build system broken on MSVC because of pragma once. IIRC it was an issue with symlink.


The annoying thing is that in spite of the fact that everyone (including the bizarrely malcompliant and bug-ridden bcc32 compiler I use at work) supports #pragma once, it will never get standardized simply because pragma anything is supposed to be strictly implementation-defined.


> It's 2016, I don't want to have to write another freaking include guard.

I'd say there are bigger issues with C++ than include guards, but include guards should be out when modules are in the standard (2020?).


Modules are a gargantuan step forward. While we'll likely never get the effortless compilation speeds achieved by Pascal, hopefully the three day build on top-of-the-line hardware is a thing of the past.


It's pars pro toto, yes what I actually need is modules to do the whole forward declaration pimpl extern template stuff for me.


> and calling it C++

We used to call it C+. It was code that could not be compiled by a C compiler. But at the same time was painfully obvious that it was not proper C++.


I think there is this misconception that there is a 'proper C++'. C++ was designed to support various programming styles, including this 'transitional' style where you have a C codebase that you slowly convert to a more object-oriented style, but overall it still remains an ugly mix of the two.

What makes C++ proper is pretty much what code style and best practices your organization/project decides to adopt. For some projects, 'proper' may be object-oriented C++ with class hierarchies, whereas for others it may be a more functional or template-based style that doesn't even use classes a lot.


As C++ features started to creep back into C you'd see a lot more of this. The // comment identifier is perhaps the most famous of these.


const came first.


Nobody in the C world really cares about const, it's extremely rare to see it in the wild. The // comments, though, are ubiquitous.


Yet another proof why C software is so safe, when comments are more important than correctness.


The const keyword has nothing to do with correctness and everything to do with helping the compiler understand which values are immutable and can be optimized.


I don't get to write much C++ code at work, given that we switched focus to become mostly a Java/.NET shop around 2006.

Even C++ARM was already a pleasure compared with bare bones C.

I has lucky to be able to bring Turbo Pascal best practices into C++, and that Borland had very good tooling.

On my opinion, Turbo Vision, Object Windows Library and Visual Control Library beat anything that I saw from other vendors in regard to C++ frameworks for desktop applications.

It always saddened me that given C++'s compatibility with C, most vendors would just throw over the fence a C library and it was up to us to create sane C++ bindings for them.

A good example is the sad state of database bindings.

But I do use C++ on personal projects, and C++11/14 has been quite rejuvenating and I do enjoy using it, specially for hobby coding across mobile OSes, given that it enjoy first class support in all SDKs.


When I was just starting programming, I was taught that if you use printf, it's not real C++. Over the years that followed, I slowly learned about all the trade-offs involved with iostreams, and I became increasingly distrustful of complaints that were not about specific problems, but just that similar code would be possible in C.


Most C++ programmers I have known wrote C++98 as C and did a crap job at it. [0] However C++11/14/17 are almost like new languages in a way. Using C++11 or later is actually a lot of fun, it isn't the horror show it used to be. Not as comfy as C# or Java but not like walking on broken glass anymore :)

Edit [0] Not saying I was any better :o)


I'm on a similar boat. The biggest change for me was to recognize that I'm not the one who's supposed to be doing the debugging. The more (modern) C++ I wrote, the more I found myself leveraging the compiler to find bugs for me.


Back in the day, embracing the STL and Boost way of doing things, and treating C++ less like "Java where you have to write * in variable declarations", certainly did a lot to improve both productivity, and my enjoyment of the language.


Yes, pointers everywhere, gratuitous use of the heap and deep class hierarchies is often derogatively called Java-style, but to be honest that's unfair to Java as that style predates it; Java was explicitly designed to make that style usable.


As a non-C++ developer, I'm curious just how many developers who choose C++ are using Boost. From what little I have heard from friends, it seems that C++ essentially implies using Boost - which could be seen as a good thing, or a really really bad thing.


Well. One doesn't have to use boost ever. I'd assume that most C++ programmers out here don't use boost on a daily basis.

At the heart of the languages, in C you can only make additions and divisions, in C++ you can also make classes and use containers to store data.

These are very low level building blocks, it's not enough to make any meaningful development productively. You're forced to use 3rd party libraries if you want to achieve anything. (e.g. File, IO, Socket, Thread...)

There are many libraries/frameworks out there. I'd dare saying that C and C++ are extremely fragmented [by domains, platforms, tools...].

There is a minor subset of the desktop C++ developers that pick Boost as the default library choice and try to put that in all projects. They're just very vocal on StackOverflow [and all over the internet].


I would say, as an heavy boost user, that today boost is no longer required. Most of boost basic utilities have either been incorporated in or superceded by the standard library.

Boost is still very useful for many advanced or domain specific libraries.


There are still a lot of minor conveniences, like lexical_cast, or uuid, or various helper algorithms (esp. for strings), that aren't subsumed, or at least not fully.

Also, one big deal is Asio. Which, granted, can be had separately from Boost... but Boost offers a convenient place to get it along with other minor stuff.

Then there's the question of how up-to-date the C++ implementation you're coding against is. A lot of stuff is nominally in the standard library, and if you use the latest and greatest, you might even have it out of the box... but for many people, they're still working on, at most, C++11 compilers, and so they need an outside source for stuff like filesystem.


It is largely driven by the choice of framework.

If you use Qt, for example, it is likely that you will also use their collections, streams etc, rather than STL and Boost.

Ditto if you use MFC (though thankfully that is largely relegated to legacy code now), wxWidgets etc.

Having said that, Boost has, to significant extent, become the prototyping sandbox for things that are then added to C++ standard proper - shared_ptr, any, variant, filesystem and many others all originated in Boost, and after many years of use and polish by the community, became (or are in the process of becoming) a part of the C++ standard library. This makes Boost more important than it used to be.


C++11 and 14 are the reasons I started to enjoy C++. I still dislike the cumbersome build process around of it but at least the language itself has become something that is nice to use.


I have a question. I often see titles of blog posts or books such as "Learn Modern C++" or "Learn Modern Java" but how possible or practical is this for a newcomer when the languages have been around this long?

For instance what happens if you opt for the strictly "modern" just Java 8 or C++17 type approach to learning these. And then you end up as the case in the real world needing to maintain legacy code? Or you collaborate with people who have been using the language for a long time but don't use these modern approaches?


"Modern C++" at least partly refers to generic programming techniques that were popularized by Alexandrescu's book "Modern C++ Design"; a lot of the features in C++11 improve language support for such techniques.

The term also implies use of RAII[1] which is a technique that was used at least a decade before C++ was an ISO standard.

The third implication is a rejection of what is often called "C+" or "C with classes" which is the treatment of C++ as C with a couple extra features. Since a lot of early C++ programmers were C programmers, and a lot of early C++ compilers were fairly mediocre in their implementation of language features[3], the 90s generated a lot of "C+" code.

Really the first two points are a subset of this one as they are two prominent examples of programming techniques that are fairly foreign to C, but are extremely valuable for writing robust C++ code.

So "Modern C++" really means "Something widely considered a good idea for about a decade" at this point.

If you work on a good legacy code base, the typical old oddness will be "Version X of MSVC/GCC/whatever had poor RVO[2], so we did this ugly thing for optimization" and (obviously) either a complete lack of using the features in C++11 or using a proto-version of them via Boost.

Even the nicest legacy code bases will have really odd things whose original motivation would require serious archaeology to divine, but that happens even with relatively static languages.

1: https://en.wikipedia.org/wiki/Resource_acquisition_is_initia...

2: https://en.wikipedia.org/wiki/Return_value_optimization

3: Believe it or not, a lot of the code from Alexandrescu's book could not compile in either MSVC or GCC when it was published. The library that accompanied the book became incorporated into many compiler vendor's conformance testing.


These were all great comments thanks. Would people still suggest Alexandrescu's book "Modern C++ Design" as the best source for newcomers to learn modern C++ then?


It is one source yes.

But you should also have a look at "Tour of C++" and "Elements of Programming".

Also Microsoft has lots of Modern C++ talks on Channel 9 done by Stephan T Lavavej.

https://channel9.msdn.com/tags/STL/


Thanks for the recommendations. Cheers.


The point of learning the "Modern" style is so that the newer, safer features are the ones you think of when writing new code. No matter which style you're first introduced to, you're going to end up coming into contact with a lot of different programming styles. Given that you may have to learn them all eventually, and that you've got to start somewhere, doesn't it make sense to introduce students to the features of the language that try to correct past mistakes?


A lot of what is considered modern C++ uses very advanced ideas. See this function from GOTW 94 [1], which Herb Sutter references approvingly, calling it "easy:"

    template<class Container, class Value>
    void append_unique( Container& c, const Value& v ) {
        if( find(begin(c), end(c), v) == end(c) )
            c.emplace_back(v); 
        assert( !c.empty() );
    }
Sutter likes this because it's written against an (conceptual) interface "Container", not an implementation like std::vector. He brags that not a single specific type appears anywhere in the code, making it much more powerful.

This is modern C++, and it is totally inaccessible to a newcomer. It hits you with templates, iterators, and several generic STL functions. Call it slightly wrong, and you'll get an avalanche of impenetrable error messages. Dig a little ("what does emplace_back do?") and you're confronted with allocator traits, placement new, perfect forwarding, etc.

Modern C++ is just not accessible to newcomers. The same thing in C (non-generically) would use concrete types and a for loop.

1: https://herbsutter.com/2013/08/12/gotw-94-solution-aaa-style...


I've never written code like that, nor am I a C++ guru by any stretch (maybe I've written two hundred total hours of C++ in the last five years, and none before that), but that code makes complete sense to me at a brief scan. And, sure, it's not the simplest way to do it, but those simplest ways exist (and are superior to the way you'd do it in C)--I mean, the same thing in reasonable, idiomatic C++ would use a for loop and an iterator, and Sutter wouldn't yell at you for it. He might hope that eventually you become comfortable enough with templates to not be freaked out by that piece of code, but he wouldn't be mad at it.

It could be that I have experience with other statically typed languages, or that I have spent time internalizing why C++ works (from a conceptual, hands-off perspective) as opposed to just how, but...that seems reasonable to me. I probably wouldn't write it that way because I don't have code that relies on that kind of flexibility, but it's quite comprehensible. If your complaint is merely that C++ expects you to know stuff to read it...I mean...yeah, sure, it does, but if that's a problem we have deeper rot as professionals to deal with.

And it is a problem, given how much we venerate C while it keeps on being wholly unsafe at any speed. But, hey. Some of us need buffer overflows to stay employed, I guess.


Mentioning the job security factor of C in a C++ discussion is ... quite bold.

On average, C++ has the highest (talk + best practices + monstrous refactoring) / (actual code) ratio of any language I know.

The C++ projects I worked on moved at a glacial pace, with constant discussions about the best object hierarchy, patches because some compiler had a different interpretation of the 100+ nested templates than some other compiler, and so on.

Oh, and the code also segfaulted and was buggy.


I write and have written exclusively C++11 and C++14. I have not written legacy C++, nor do I have a cause to do so (though I have had to wrap around that code at times). The C++11 and C++14 code that I see is generally clean, adheres to straightforward memory models (heavy use of references and smart pointers), and has pretty straightforward and comprehensible OOP design.

There are developers who assert that C++11 is a step change of a language from C++98, and that may be true, but reasonably written, stdlib-adhering C++11 and C++14 are solid, hard-to-break languages in the general case and horror stories with regards to C++98 seem curious unless one wants to bring up failures of early DHTML applications in conversations about React.

(The build environments? Often a different story.)


> I write and have written exclusively C++11 and C++14.

I am skeptic of what this sentence is supposed to mean. Well, except that you've programmed in C++ for a very short period of time, in what seems like a very particular environment.

As far as I'm concerned. C++11 and C++14 came out with no design guidelines, zero different way to organize the code, no coding guidelines, no good practises. Just like C++03 before it :D


> I am skeptic of what this sentence is supposed to mean. Well, except that you've programmed in C++ for a very short period of time, in what seems like a very particular environment.

By choice. I use C++ where I absolutely must and nowhere else. It exists for particular use cases and no others. If I need high-performance native code with a strong(-enough) type system and I can't use Rust, I will use C++. Why would I use it elsewhere?

I have been using C++ for about five years, which by some lights is a short period of time--but, then, I've also been programming for twenty and I can comfortably say that I understand the hows and whys of C++ as a language even if I don't practice it heavily. (I learned them even before I used C++ at all because they reveal the particulars of the underlying techniques used by other programming environments, such as the JVM.)

And C++11 and later is pretty easily made straightforward, comprehensible, and manageable. (I mean, if you only stuck to the axioms of "never pass a pointer" and "always use std::unique_ptr and std::shared_ptr" you'll have code that's leaps and bounds past C++98/03 or anything written in C.) I write it in such a style and the code I'm exposed to generally does, too. Sorry that you don't?


You can read code in most languages and guess at what it does. But that doesn't mean you can write it - or debug it.

I'm not complaining. Herb Sutter has his arguments for why experts should write code this way.

But I don't think newcomers should attempt to write in this way. You can't understand iterators before you understand pointers, or templates before concrete types and functions, or emplace_back before push_back, or Concepts before classes, or auto before concrete types. You may be able to use them, but you won't understand them, and you'll be useless when things go wrong.

One last illustration: you mention your experience with statically typed languages. But C++ templates provide much less static type checking than non-template code. It is definitely not a place to start.


C++ templates provide type checking exactly within their bounds, which this particular example illustrates, so...well, what? Posit for a second that you are correct. I think you're not, but let's posit that you are. And then I just think...so what? I don't mean that to be flip: what's the point of your post if it's not to air complaints that "newcomers might have trouble"? I mean, yeah, all things being equal, approachability is nice--but newcomers have trouble with chainsaws, flying planes, and 240V wiring. Hard things are hard. C++ is hard. It's why it's a tool of last resort, if you are wise. If you're not, nothing's gonna help you, yeah?


It's funny. Go programmers are unhappy with the lack of generics (templates), complaining about the lack of type safety in interfave {} (void* in C).

Looks like some people like that approach.

Guess you'll never win


'There are two kind of programming languages: those that nobody use...'


While "easy" is rather subjective, I would say this: if you already know the basics of the standard library, then this is indeed quite easy. For the most part, it's not even remotely modern.

- it's a simple templated function; could even be reduced to one parameter if you use "typename Container::value_type" for Value - it's using find (standard library algorithm) - it's using begin and end (iterators common to all standard library containers) - it's using emplace_back (new to C++11 with rvalue refs, but everyone already knows push_back which it replaces)

While emplace_back might be new to people using C++98, everything else is well over two decades old. It's extensively documented, and if you've ever done anything with the standard library, it's basic stuff. If any C++ programmer struggles to understand this, then they are essentially stating that they don't know the basics of the standard library or the language.


I wouldn't consider that anything close to beginner-level C++ because, as you said, it bombards you with a ton of concepts all at the same time. It's the kind of thing that I'd want put into some library and not look at it.

All that I'm trying to advocate are things like smart pointers instead of raw pointers and relying on iterators so you can use range-based for loops. Avoid some of the classic problems like forgetting to de-allocate things, de-allocating twice, using out-of-range indexes, and all that.


> Or you collaborate with people who have been using the language for a long time but don't use these modern approaches?

That's always going to be a problem, but that's no reason to not learn the latest versions.

> And then you end up as the case in the real world needing to maintain legacy code?

It's not like learning the newer ways of doing things prevents you from learning everything else.


You cry, and use them just on your own private projects.

Additionally keep looking for opportunities to sneak in some features, or pushing for toolchain updates.


Is anyone using Stroustrup's C++ Core Guidelines? And GSL? https://isocpp.org/blog/2015/09/bjarne-stroustrup-announces-...

They look like a way to add some safety to pointers and memory allocation, for those who demand bare-metal performance. Wondering if it's taking off...


Does anyone know if the videos from this conference have been posted somewhere? The slides are. The talks referenced in the author's post sound really good.


They have a channel here, looks like they're still in the process of uploading the talks - https://www.youtube.com/user/MeetingCPP/videos


Oh brilliant. Thanks!




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

Search: