Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
C++17 and its Technical Specifications (meetingcpp.com)
87 points by meetingcpp on March 3, 2016 | hide | past | favorite | 68 comments


The C++ standards committee and community has really been firing on all cylinders lately. C++ has made such enormous strides in the last few years. If you've been away from C++ for a while, check out modern C++ again. You'll be shocked by how good it's become.

Just keep away from the Google C++ style guide lines. They'll lead you very far astray.

Check out https://github.com/isocpp/CppCoreGuidelines/blob/master/CppC... for a good start on modern C++ style.


> Just keep away from the Google C++ style guide lines. They'll lead you very far astray.

Huh. I think Google C++ style guide makes a lot of sense. C++, the good parts.

What's wrong with the guide in your opinion?

I know a lot of people might disagree, but the common criticism of Google's C++ style, exceptions, tends to be a misfeature when you need to actually handle the errors.

It puts error handling code far from where errors occur, and where you often have the best chance to deal with it. It also obscures error sources, it's not immediately obvious in local method context just by looking at the source code which calls can throw and which not.

Exceptions also don't undo any I/O that was done, so things might be in pretty bad state -- and it tends to be pretty bad to deal with that a few method calls up.

I like errors to be on my face, even if they're "ugly". You tend to forget about hidden things.


>It puts error handling code far from where errors occur, and where you often have the best chance to deal with it

So, you pass file name to your data access library and the file is not there. How are you going to deal with it? Write an error to the log nobody reads and call terminate()? Create a new file and let users guess what happened to the data they expected? Or return an error code?

If you picked the last option (as most people do) - well, bingo, you've just put your error handling far from where the error occurred. The only difference with throwing an exception is that now every function up the call stack needs to check that error code till it reaches the place where you can handle it or, even more likely, till someone forgets to check or chooses to ignore it. Because, unlike Go or Rust, C++ compiler won't help you there.

Error codes don't undo I/O either.

As to "which functions can throw" - let me suggest a simple rule: every function can, unless you can prove otherwise.

Look, there are situations where it makes sense to avoid exceptions, but not for the reasons you listed. Exceptions are the least evil way to handle errors in C++. Google style guide bans them mostly for historical reasons, let's not cargo cult it.


> So, you pass file name to your data access library and the file is not there. How are you going to deal with it? Write an error to the log nobody reads and call terminate()? Create a new file and let users guess what happened to the data they expected? Or return an error code?

Perhaps return an error code. Which the caller would check and deal with the error. (Besides, I'd be passing a stream object, not a filename.)

I/O is also network packets, graphics on the screen, motor movements.

> P.S. As to "which functions can throw" - let me suggest a simple rule: every function can, unless you can prove otherwise.

Exactly, that's the problem.


How about wrapping the return value in a templated error class that the caller has to explicitly unwrap with an error handler to be able to use?


That will help if there is a value to return - but then it's not much better than just returning something invalid, like a NULL pointer. If the only return value is success/failure you need compiler support (1) to ensure it's not ignored.

(1) There are clever hacks to mimic this behavior to some extent, but I don't even want to go there. If you really want this feature - just use a language that has it.


You also tend to overlook/ignore the "if err != nil" in every other line, which Google seems to push. There is really no silver bullet for error handling, and sometimes you need more than one approach. However, I think exceptions are usually the best, especially because they work very well with RAII.

It would be great to have some function annotations to show which exceptions can be thrown, though. But still, keep in mind tha Google's style is pretty much equivalent to having a catch(...) after every call.


>It would be great to have some function annotations to show which exceptions can be thrown, though.

There was [0]. It is deprecated and generally discouraged, since it quickly becomes a maintenance nightmare (since you have to include unhandled exceptions for all functions called from that function, etc, all the way down).

[0] http://en.cppreference.com/w/cpp/language/except_spec


Exception specifications (deprecated) aren't the same as checked exceptions, which I think was what some people might have in mind. In theory, they look like they solve a number of problems, but in practice they really create more than they solve. Even Java language designers have said that checked exceptions were a mistake.

The noexcept keyword was actually added to address some of the limitations.


I agree that these things get ugly very quickly. Another thing is that you aren't always catching all exceptions; for example, sometimes you are sure that something is in bounds, but the function is still declared as throws(out_of_range) or similar.

Is there a better way to do it, maybe a static analyzer or IDE warning about possible exceptions?


Instead of exceptions, I personally prefer using assertions to verify things like preconditions; in which case if an assertion fails the software should generally crash before getting into a worse state. Arguably, if the software shouldn't crash it's probably not an exception. Assertions can also give an analyzer a set of preconditions to check. For example, Clang's static analyzer parses assert statements [1]. I'm not sure it uses them to verify the preconditions, but regardless it's still a good way to express them.

Another way to express constraints are attributes, which static analyzers (and optimizers) also use. For example, GCC has a number of function attributes [2] to express invariants about code.

[1] http://clang-analyzer.llvm.org/scan-build.html#recommended_d...

[2] https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attribute...


My current least-favorite parts of the google style guide are 'don't overload operator< and std::hash, but keep them as free functions and use the other ctors for set/unordered_set/etc', because I'm thinking if you're going to have to write those things anyway, you might as well do it in a way to make the api easier.


While modern C++ is pretty nice, I still think D and Rust have completely eaten its lunch. At this point I think the only thing C++17 does better than D or Rust is brand recognition. :P


I don't think so.

The advantage of C++ is that it borrows C's syntax. You can't beat the simplicity of C's syntax. I don't really care about C++ backward compatibility with C, but so far, when I read go, rust, and sometimes D, it looks alien and a little too complex to me.

Not saying C++ templates are good enough, but I think there are not many languages out there with a concise, limited syntax like C or python. Being easy to read and easy to learn is the most important aspect of a programming language. There is python, which really excels in this particular aspect of what makes C great, but I can't really think of any other language which is as much easy to read or comes close.

D is a good contender, but not everybody needs high level, multi paradigm and speed, and are ready to learn something new, especially when you can't reuse C++ libraries.


Here starts the rustwin point.


Modern C++ isn't really that fun on Windows either... (no Valgrind, GCC and Clang are ported later, many fewer libraries)

D on Windows is surprisingly pleasant though.


I read the comment as a reference to Godwin's law, not Windows.

Rustwin's law: As discussions of C++ grow longer, the probability of a comparison to Rust approaches 1.


Derp, how'd I miss that. Yeah, I bet that was what the parent meant.


Microsoft has been very active in the standards efforts. Valgrind missing is painful, but there are windows-specific memory validation tools as well. I'm a Linux developer though so I don't feel that pain much.


Do Clang's sanitizers work on the Windows?


Rust is very exciting but the ecosystem needs to grow before it'll be as useful as C++. Fantastic language, thoughtfully designed.


Is there a way to suggest language features to them?

One think I would like to see in C and C++ is labeled break/continue:

  while(foo) {
    while(bar) {
      break 2;
    }
  }
and/or

  baz: while(foo) {
    while(bar) {
      continue baz;
    }
  }
Similar to goto, but break baz would exit the while loop, not start it again. And using continue instead of goto is more idiomatic.


Can you suggest a use case, assuming modern best practices, where this would improve readability/understandability and ease of testing? That kind of control flow looks a bit scary to me.


Say you are processing CSV files line by line (outer loop), column by column (inner loop).

You come across something in the data the means stop processing that line and skip to the next one.

So you do 'continue 2;' to skip the inner loop, and anything after it (presumably the code that would do something with all those columns you just got) and simply start a new line.

There are lots of use cases.

Obviously there are other ways: You can use a goto, you can set flag variables, you can use functions in the inner loop to give you a way to exit early.

But this type of control flow is easiest to read. Many other language have this BTW. C doesn't.

It's also good for error handling. If you find an error in the inner loop how do you exit that loop, and the outer one? You would do 'break 2;' and exit both loops.

The labeled version is because using a number is prone to errors if someone changes how many loops there are.

Do a search for 'goto' in high quality code and see how many of them can be replaced by this - it's the vast majority.


But why? I mean, if I understand correctly, it would be exactly like goto.. so, why not use goto instead? You could also have named labels to clearly describe where you want to jump and why.


I'm very excited for networking to FINALLY be part of the standard. Practically every modern language has networking capability in their standard libraries.

The day I can pick up C++ and, without including any third party libraries, write my own web server in a minimal amount of code will be the day I start using it more. Too much of what I do nowadays requires some form of networking.


Yeah I was a C++ dev for 12 years before switching out. I miss being able to hit the metal, its depressing to work with Python Pandas that are advertised as "nearly as fast as C". Meanwhile our main Java app has huge GC lockup problems. Hopefully C++ will soon be at a level I can recommend it for business applications again.


Sounds like you could take a look at D as an alternative to Java if you want to hit the bare metal and still have (optional) GC. I like D a little more coming from a C# / Java background but wanting something more natively compiled.


s/D/go/g


Only mentioned D for being Object Oriented with classes.


It looks like they used most of ASIO except for their SSL support. So it will be up to the SSL library makers to add support for std::experimental::net::basic_socket.


This will probably be an unpopular position but: I really hope concepts doesn't make it into C++17. Not because I don't want concepts, but because I think definition checking is completely integral to what I want them for.


Even if definition checking is very important, why not implement the full specification in two steps if it helps to make it happen ?


Because once you ship it without definition checking, three years later it's too late to add it. Too many people will have written code that will break. This is one of those unfortunate language features that you only get one chance to get it right. Note: I haven't been following this stuff closely, I could be missing something here, but I trust that someone will correct me if I'm wrong. Or at least down-vote me to oblivion :)


The current specification create a "concept" keyword. Why the fully checked concepts couldn't just use another keyword like "checked_concept" that behave exactly like the "concept" keyword for user of the library ? Library implementers can then migrate progressively their code when they can.

edit: or, alternatively, create a "checked_template" keyword when implementing a checked template.


In any event, it looks like concepts have indeed been kicked to the kerb. I think the definition checking was important, and some were concerned that there was no library implementation using it, which means they haven't shaken it out in practice yet.


I thought that was one of the big selling points back when they were aiming for C++0x: "your compiler errors will make sense!"


Was the coroutine proposal droped from C++17 ? That was one of the most exiting feature


No, that is not dropped, but it also is not contained in a TS yet, I'm not sure if it gets added to C++17.

There is a wording paper: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p005...

Not sure if Jacksonville will already give green light or if this will be decided later. Would be a good addition though.


A Microsoft specific implementation is available in Visual Studio 2015 and possibly earlier.


std::optional seems to have been in gestation for ever, and we're crying out for it. Is there some complexity issue here that I'm missing?


One reservation I have about “optional” (and for that matter, “shared_ptr” and other objects that directly store their tracking in an object) is that object-oriented storage models do not necessarily make sense for tiny objects.

If you have a lot of optional data, or a lot of reference counts, etc. it can make a lot more sense structurally to gather the state of all variables in one place. For instance: if you have 10 optional fields in a structure, create a single set of 10 bit flags to track them all; the result is much smaller than 10 “optional” objects ever could be. The last thing you want is a ton of padding across millions of objects in your program; this starts to affect everything from efficient use of caches to maximum memory capacity.

It just seems a bit of a slippery slope; optional<> might start showing up all over the place as the One True Way To Optional things, without regard for the unnecessary padding and/or wrapping of data.

The only way to really do this “for free” is to have the compiler keep track of what was ever set, as Swift appears to do, keeping the tracking out of the memory or run-time footprint.


People often use a vector of vectors as a matrix. It's not as efficient, it usually is a bad idea, yet it doesn't discredit std::vector.

I suppose we could create a variadic template std::optional<...> which works like a tuple to solve your padding concerns.


When will there be a C++XX that will actually remove bad features? Of course with a migration plan and tools.

C++ standard is pretty big, I don't personally know anyone who really knows C++.

I write C++ as my day job.


Scott Meyers (of Effective C++ fame) has a great blog post on breaking backwards compatibility [1]. Unfortunately, he views it as a 10 year process.

[1] http://scottmeyers.blogspot.com/2015/11/breaking-all-eggs-in...


There have been deprecations like auto_ptr and gets(). But I assume you're looking for more.

You aren't going to get it. C++ is just not that language. It isn't going to have a Python 3 moment. Nor should it.

I for one am glad to be able to upgrade to new versions of the language without having to rewrite much.


Complete breaking is never going to happen. What can be done is adding compiler switches which enforce some kind of "strict" or "modern" mode. Something close to "-Wall -Werror", but with errors explicitly for the deprecated/bad features.


Actually, my proposal to remove auto_ptr etc. from C++17 was accepted: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n419...


I've given a number of talks on the parallelism TS at C++ conferences and fully believe it can revolutionize the C++ libraries, I really hope it can make it into C++17.

Having such easy parallelism techniques within the language would be huge, I can think of so many scenarios where stupid-parallelism can be applied using the STL. The only set back is the additional room to shoot yourself in the foot, people that don't understand the overhead of parallelism could easily blow up a program in terms of efficiency.


The guys who've been prodding us to use chevron IO in lieu of printf and to pepper our code with gems like the for_each "algorithm" are back, and they have some new awesome features for us. Thanks, guys.


Other question: do you think that writing a compiler that only work with C++14 or 17, might compile code faster ? Or will C++ always be slow to compile ?

I'm still wondering what makes go so fast to compile.


Not currently. I think it can be largely attributed to header files, for which we currently have no solution in modern C++. Think about what your code would look like if you expanded all #includes of a single file, each containing entire class definitions that need to be parsed.

One of the proposals for the next C++ standard is for modules, which would allow better symbol importing and would largely boost compilation speeds, among other benefits.


Finally "then" for futures ! Yay !


Risking downvotes... all this stuff seems a bit boring. For example, since the start C had ways to access the disk, C++ gave us ifstream's and now C++17 has filesystem - yawn.


ifstream is very, very limited. Shocking as it is, there's still no standard and portable way in C++ to do very basic filesystem operations, like list files in a directory - you have to use platform APIs or third-party portability libraries.

Seems like C++17 finally resolves this. We only had to wait 34 years :)


That's because C started as a language rather than a platform. You have always needed to marry it to POSIX or Win32 or whatever to do anything useful. Now with various proposals like 2D graphics, C++11 threads etc. it looks like they are moving in the portable platform direction.


Yes, I know. We had this "C runs on systems that don't even have disk" excuse for so long it's became a cultural thing.

I'm not sure where to draw the distinction between a language and a platform and I don't think I care. Those additions will make C++ way more useful, libraries will become more composable, binaries smaller, and life will be easier for 99.9% of people who use C++. So, I'm glad they finally dropped the lowest common denominator approach - we've been making our own batteries for way too long.


I think it's more of a philosophy than an excuse. I'd say it's only in the Java era that people have started expecting their language to have "batteries included." Big ships like C/C++ turn slowly, but it does seem to be turning that direction. Whether that's better than the community defaulting to boost libs, I don't know.


You're right about changing expectations, but it is better. Really. Too many people view boost as a giant cumbersome blob of libraries interconnected in unintuitive ways and refuse to use it, especially if they only need something that they perceive as small and simple.

We've been through the same exact arguments years ago, only then it was about things like std::string. Oh, no, it allocates dynamic memory behind the scenes - there are systems that don't even have heap! As a relic from that era some popular libraries still use their own string classes.


I've been using Qt for years to do this. I have my fingers crossed I can finally use the standard libraries.


Well it is basically an almost-copy of Boost.Filesystem which you can use today, can you not?


Boost requires compiling libraries ahead of time and linking them in, so to do that on top of Qt would be asking a lot for very little gain. If filesystem was a header only library I don't think it would be as much of an issue.


I assume that in the long run Qt will relinquish this to standard libraries, so QFile will basically be a convenience wrapper around std::file integrated with Qt's concurrency model.


Well, boost::filesystem exists for ages...


But how many million lines of header files do you need to pull in to use it?


Probably as many millions of lines the C++ standard will use, since its based on boost::filesystem.

A lot of these proposals and the changes in C++ this decade have just been standardizing slightly modified versions of Boost libraries.


>Probably as many millions of lines the C++ standard will use, since its based on boost::filesystem.

Not necessarily. A lot of boost contains workarounds for compilers that don't support certain features. Since the standard library will be expected to be used with a known compiler (or at least a new-ish compiler), it doesn't need workarounds for missing C++11 support, etc.


The biggest problem with Boost isn't simply the number of headers - it's maintaining the built libraries against your compiler.

"Let's upgrade to MSVC 2015!"

"Oh nuts, our code now links against msvcrtp13.dll and our built boost_filesystem.dll still links against msvcrtp12.dll. Time to rebuild all of our libraries!"

This is especially bad on Windows where MS's dev tools team just didn't 'get' that developers just don't care about new CRT optimizations if it means rebuilding all of our 3rd party libraries. But even on OSX there's been the whole libstdc++/libc++ pain.

Anything that can get folded into the standard library and maintained by the same jokers who rev msvcrt*.dll every couple of years (rub their noses in their own mess) is good.




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

Search: