back
342 comments
When I started writing C++ around 5 years ago, I had a perception that it was a language that is "on its way out". As I learned more and more of it, I've been super impressed at how modern it is becoming, and how it is adapting to overcome its perceived flaws. It is becoming a killer language to me: blazing fast, modern, ubiquitous, stable, and expressive.
Too bad it's a mirage. No, really. "Modern C++" doesn't exist outside of blog posts, books, and tutorials.

Real-world C++ is an array of sometimes mututally-exclusive dialects, patterns, rules, sub-dialects.

Reading MFC is nothing like reading Qt which is nothing like WxWidgets which is nothing like Boost which is something (but not quite like) the STL which is way different from Apache C++ libs which is way different from what Google's C++ libraries are...

This is what happens when a language is "un-opinionated", throws everything including the kitchen sink at the language, tries to compile C and legacy C++ while introducing new features oh and also can't break existing code.

It's on its way out, no doubt about it. And we'll be better off as an industry for it, I'm sure of it.

Rust, Go, and others will be there to fill in the gap in a much better, saner, safer, maintainable way.

This is totally true. The downside, of course, is just how much code exists that is written in pre-C++11 dialects, and how many programmers are trained to write that sort of code.

I like way more of C++11 than I liked of the prior version, but there's just so much that's accumulated over the years. I wonder if breaking backwards compatibility is the key, but then I look at Python 3 and think, well, probably not.

I _completely_ agree. I think people need to start talking about how, when combined with the right tools and compilers, you can achieve nearly anything you can with another "modern" language more expressively and faster, all while being compatible with decades of massive c, c++, and objective-c libraries.

Perhaps we should start with dispelling the old notion that one "shouldn't use" the STL.

You should check out what's planned for C++17 https://isocpp.org/std/status if you haven't yet.
OT question: I was playing with some C over the weekend (not C++), trying to figure out how to handle Unicode in a way that would work on Mac, Linux, and Windows. Despite a couple hours googling and reading, I couldn't answer really basic stuff, like:

- Do I use char* for strings? It sounds like wchar_t is 16 bits on some systems and 32 on others, so I should avoid it?

- If I want to read & write UTF-8 files, how do I turn the bytes into 32-bit wide Unicode strings?

- Are there special functions I should use for handling Unicode strings?

More generally, where do you go to discover C libraries you can use?

I am (was) reasonably proficient in C, but I haven't used it much for over ten years. I'm surprised how many things I just don't know how to do!

Sorry this is not a C++ question. I'd like to get back into that also, but I'm trying to work my way up from the basics. :-)

C++'s support for unicode is minimal. There are unicode string literals for UTF-8, UTF-16 and UTF-32, and conversion facilities between those encodings and the host platforms native 'wide char' format.

> - Do I use char* for strings? It sounds like wchar_t is 16 bits on some systems and 32 on others, so I should avoid it?

In general you should use std::string and UTF-8, since UTF-8 is a relatively safe encoding for sub-string search and replace, and (locale insensitive) lexical comparison/ordering. Windows uses a 16 bit wchar_t (UTF-16). Mostly everyone else uses 32 bit (UTF-32)

> - If I want to read & write UTF-8 files, how do I turn the bytes into 32-bit wide Unicode strings?

http://en.cppreference.com/w/cpp/locale/wstring_convert

> - Are there special functions I should use for handling Unicode strings?

Nope. You need a library for that. Manipulating natural language is a tricky business anyway, beyond single mortals, and you will likely get it wrong.

Look here: http://userguide.icu-project.org

You really need a library when dealing with unicode, if you are doing anything advanced.

How do you split a sentence into words? Spaces, right? Oh, Chinese doesn't have spaces.

How about sentences? Paragraphs? Even characters are a pain to iterate over.

C11 has the uchar.h header (say, http://www.cplusplus.com/reference/cuchar/ ), but it wasn't in Visual Studio last I checked.

Most programmers will tell you to use UTF-8 for in-memory strings. But it's not easy to figure out if a particular char* is already encoded as UTF-8, and it's common for people to forget that Unicode characters can take up to 6 bytes in UTF-8. I know I'm in the minority, but I prefer to use UTF-16 or UTF-32, because nobody makes the kind of mistakes with UTF-16/UTF-32 that they make with UTF-8. Plus, you can't accidentally pass a UTF-16-encoded string to a non-Unicode-aware function.

Why not just write C style C++? I never understand the arguments to use C anymore - you can write C style C++ and get on with your life, and cherry pick the features you want.

In C++ unicode is as simple as: string s = u8"This is always a utf8 string.";

You can grab and compile the very latest draft from the committees Github page:

https://github.com/cplusplus/draft

The current version is a slender 1365 pages, including the standard library.

I see a lot of discussion around C++ becoming modern. I would like to know which features are actually modern?

Is it lambdas? been around for literally decades. Is it type deduction? again been around for quite some time, far better type inference has been available in the likes of Haskell for quite some time. Is it addition of a particular threading model to the standard? this has always been available via some form of library, it just know means the language is truly obsolete if the model changes. Allow GC'd implementations? again decades.

What is modern about any of features that have been added?

> What is modern about any of features that have been added?

Nothing. On the other hand, which features of a “modern” language are missing in C++ by now? Type deduction is still a bit less powerful than in Haskell, yes, but apart from that I can’t really think of anything that may or may not be missing.

This in turn implies that C++ allows essentially any style of coding you may wish for at the moment while at the same time staying some orders of magnitude faster than essentially the entire competition.

The way all those languages are used together.

Not writing modern C++ means:

- writing C++ as if it was plain C

- doing OO programming with big object graphs

- manual memory management

- not using the standard containers and algorithms

- writing functor objects

C++ is 35 years old and predates Haskell and many other "modern" languages like Java, C#, Python, ... So yes, compared to what C++ was originally, it has become modern.
I would like to know which features are actually modern?

Close to none of course, but that isn't the point AFAIK.

The point is all of them have now been added, hence the 'modern' connotation, and another part of the point is that C++ now even more is a language rather flawlessly combining all those paradigms.

Do you know where I can find a diff?

I'd like to see whats new with 14.

Edit: http://en.wikipedia.org/wiki/C%2B%2B14#New_language_features

Can anyone recommend a book on modern C++?
Scott Meyers' Effective Modern C++ will be required reading once it's released in October.

Until then (and even after), Stroustrup's The C++ Programming Language (4th edition) is the canonical resource. It's a reference but is also intended to be read.

Bjarne Stroustrup, A Tour of C++.
Stroustrup's The C++ Programming Language 4th Edition (the blue one) is good. The beginning of it gives a tour of C++ in light detail but then you have the rest of the book to look at as a reference. It's actually quite an enjoyable read, particularly as it has a different font to the previous version (the white one?).
Yeah, this would be a god send. As someone who is writing more and more C++ for computer vision type stuff, a modern overview would be great. I am stuck working off of things I learned over the years and don't feel quite like I'm writing modern idiomatic C++
I apologize if this is ignorant, but how is C++ versioned?
Until now there have been four standardized versions of C++: C++98, C++03, C++11, and C++14. And the versions have been consistently named (to be precise, "nicknamed") as "C++YY", where YY are the last two digits of the year in which that ISO standard was adopted.

Note: C++03 was a very minor change (sort of a "bug fix"), so people sometime refer to C++11 as direct successor of C++98. Also in the interim (2007) there was C++-TR1 ("ISO/IEC TR 19768:2007") which was not a formal standard per se, but instead a technical report specifying bunch of standard library extensions (which were formally included in C++11)

For sake of completeness: The format C++YY is the one which is commonly used almost everywhere, but the official language name follow ISO's convention. Here is a mapping:

C++98: "ISO/IEC 14882:1998 Programming languages C++"

C++03: "ISO/IEC 14882:2003 Programming languages C++"

C++11: "ISO/IEC 14882:2011 Programming Language C++"

C++14: "ISO/IEC 14882:2014 Programming Language C++"

There are also language classifier like (E), (F), etc present at the end (e.g., "ISO/IEC 14882:2014(E) Programming Language C++"). I am not sure if the official standard is fixed in a particular language, or are all the different language translations equally authoritative (I suspect the latter, but it's just a guess).

what do you mean?

C++ is a language designed by committee. C++14 is meant as a "tock" release, fixing some of the things in the C++11 "tick" release. ("tick" releases are larger, and "tock releases fix some of the problems in the "tick" release).

Compilers then attempt to implement the standard, and have their own versioning system.

By the year the standard was published.
New features like auto and shared_ptrs.
The version number identifies the tonnage of crap that has been added since C++98.
I've started getting back into C++ after many years away and it's all coming back to me.

Now of course it's C++11, which does have some nice features, but really I think we've reached the point where we need to start again (downvote away).

Let me give you an example: I recently came across some code that was written years ago that has two size types: one 32/64 bit signed and the other 32 bit unsigned. This creates a bunch of issues when compiled on 32 and 64 bit architectures and there is a substantial amount of effort to clean it up.

I point out things like this to colleagues who are very pro-C++ and I inevitably get the same response: "well that's just bad API design".

Thing is, if you look at the history of this example it's a series of incremental changes, all well-meaning and reasoned, some of which are done by people who I could only call luminaries, and even they make significant and far-reaching mistakes.

So what hope do the rest of us have?

But my biggest problem with the C-dialects is pointers. Namely if you return or receive a pointer, it's not necessarily clear who owns it. The way this is handled is comments like "DO NOT delete this" or "you MUST delete this".

I like that a language like Rust is trying to formalize the concept of object ownership. I'd really like to see that idea mature and take hold.

Until now there hasn't really been a competitive alternative to C/C++. It's not Go (as much I love Go). Maybe it's Rust. We can but hope.

My other big problem (and this applies to Java too) is directly dealing with low-level multithreading primitives like threads, thread groups and mutexes. I really like that Go has taken a different approach here.

What I find with particularly young programmers is they don't have the appropriate fear of writing multithreaded code. It's really, really hard to write correct multithreaded code with low-level primitives. It's why (excellent) books like Java Concurrency in Practice exist.

As for the feature list of C++14 [1], I wonder what all these "auto" declarations will do to the significant work required for static analysis tools, that are an essential part of modern, large-scale C++ codebases.

The literal types (like "s" for std::string or seconds) are cute but at some point the STL was optional. I'm a little leery of embedding it directly in the language but hey I'm no expert.

[1]: http://en.wikipedia.org/wiki/C%2B%2B14

> code that was written years ago that has two size types: one 32/64 bit signed and the other 32 bit unsigned. This creates a bunch of issues when compiled on 32 and 64 bit architectures and there is a substantial amount of effort to clean it up.

Such things happen whenever an invalid assumption that is commonly true becomes not so commonly true, such as the 32-bit to 64-bit migration. That said, C/C++ provides you the tools: size_t is an unsigned type meant for storing array indexes and the size of objects in memory. If you want a real integer, then (unsigned) int. If you need integers of a definite fixed size, u?int(8|16|32|64)_t. Granted, I've encountered that not enough people take the time to understand the tool they're using. Honestly, I wish the default integer type was not fixed size, and especially not platform dependent fixed size, like Python; for non-[indexes/sizes], I feel like this is usually what you want.

> "well that's just bad API design".

Well…

> But my biggest problem with the C-dialects is pointers. Namely if you return or receive a pointer, it's not necessarily clear who owns it. The way this is handled is comments like "DO NOT delete this" or "you MUST delete this".

This is true; in C++, your use of pointers should be minimal, though this can be a problem with references just as easily. In the (special) case of std::shared_ptr, ownership is clear. That said, this is a problem not unique to C++: it exists in Java, Javascript, Python, and many others as well. For example,

    some_list = [1, 2, 3]
    some_obj = MyObject(some_list)
If some_obj expects to own that list, and it's constructor is:

    def __init__(self, some_list):
        self._some_list = some_list
which I see a lot, you've got the same problem. (I'm also interested to see how well Rust tackles this, as I agree it's a problem.)

> My other big problem (and this applies to Java too) is directly dealing with low-level multithreading primitives like threads, thread groups and mutexes. I really like that Go has taken a different approach here.

Honestly, I've never thought multithreading was "hard". There's a set of rules you have to hold yourself too, otherwise, yes, you can make your life very hard. If you limit shared data as much as possible, and what data is shared has a well defined locking order (preferably behind code that enforces it) — often this is just a single mutex — then I don't see the problem. Thread-safe queues ("channels", I think Go calls them) are also useful to establish "service" like threads.

In C++ parlance ownership of pointers is dictated by how they are stored.

Raw pointers are only views of the object passed around, these confer no ownership.

std::unique_ptr owns a single unique instance of the memory.

std::shared_ptr (and std::weak_ptr) confer ownership of the memory amongst several other entities.

The convention I use in my own code is that passing a raw pointer around, or returning one, confers ownership. Mostly I do not schlep raw pointers around between functions, though. I use shared_ptr or scoped_ptr or unique_ptr or a reference. When I have to use raw pointers with some given library, then I immediately wrap their usage in my own facade types. Sticking to these oft-repeated best practices means that crashes are rare and memory leaks are rarer still.
On pointers -

Like a lot of things with C, you need to handle ownership by convention. I generally try to make the actor that created the heap pointer the owner of it and responsible for its destruction - i.e. instead of allocating buffers and handing them back up the chain full of data, pass them down from the requester where possible. If the length is not known at that point, create another routine to calculate it. Using techniques like this, ownership can become easier.

You can do anything with it, but that's half the problem!

And personally I like threads :)

The literal types are optional— they're user-defined literals, which can be written like (say):

    QString operator""_qs(const char* c_str, size_t len)
    {
        return c_str;
    }

    void foo()
    {
         auto iama_non_stl_type_ama = "foo"_qs;
    }
Number one wishlist item for next C++ is to add networking libraries to the STL. Its past time that C++ knew about the internet.
C++ is suitable for development of cross mobile applications , since both iOS and Android tool chain has support for C++.
Are modules already kind of unofficially supported, or can they be enabled ? On what platforms ?

I'm trying to make a C++ game with fat libraries like Ogre3D and bullet3D, often on a laptop, and that would really be fantastic to not wait 10s or more each time I edit a header.

I've seen a presentation, basically modules would decrease compile time from M x N to M + N.

I really like the direction C++ is moving in. I just really don't like how incredibly VERBOSE it is (though `auto` helps).
In languages like C++ "verbose" means "specific and obvious" which is something you want to have when writing certain kinds of code.

It's annoying, it's a drag on productivity, but in the long run it's arguably necessary.

Some other languages which reduce verbosity by making more things implicit make it harder to understand what's actually going on behind the scenes. You lose a lot of information.

And we have golang.
I'm a little afraid the language will go down hill from here. Too many versions - a committee dedicated to creating new versions of the language standard is going to do exactly that. Much like has happened with OpenGL.
> Too many versions - a committee dedicated to creating new versions of the language standard is going to do exactly that. Much like has happened with OpenGL.

The problem with OpenGL was that they tried to retrofit an API that assumed a certain underlying hardware model to modern (i.e. less than 15 year old) GPUs. It was impossible to do in any sane manner.

I'm assuming C++14 will have 1320 keywords and a bunch of weird operators to use so people can ignore it even more than it's being ignored.
Speaking of ignoring things, have you read anything at all about C++14?
I don't think there are any new keywords for C++14.
If only it were true, the problem is more that c++ as to many meaning for its keywords.