8 ms·
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
by readams 11y ago
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/CppCoreGuidelines.md https://github.com/isocpp/CppCoreGuidelines/blob/master/CppC...
for a good start on modern C++ style.
- vardump 11y ago> 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.
- Noughmad 11y agoYou 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.
- sseagull 11y ago>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 http://en.cppreference.com/w/cpp/language/except_spec
- uxcn 11y agoException 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.
- Noughmad 11y agoI 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?
- uxcn 11y agoInstead 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_debug http://clang-analyzer.llvm.org/scan-build.html#recommended_d... [2] https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attribute...
- azov 11y ago>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.
- vardump 11y ago> 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.
- sbmassey 11y agoHow 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?
- azov 11y agoThat 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.
- GFK_of_xmaspast 11y agoMy 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.
- PeCaN 11y agoWhile 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
- jguegant 11y agoHere starts the rustwin point.
- PeCaN 11y agoModern 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.
- santaclaus 11y agoI 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.
- PeCaN 11y agoDerp, how'd I miss that. Yeah, I bet that was what the parent meant.
- readams 11y agoMicrosoft 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.
- santaclaus 11y agoDo Clang's sanitizers work on the Windows?
- 11y ago
- ars 11y agoIs 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.
- smitherfield 11y agoCan 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.
- ars 11y agoSay 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.
- kruczek 11y agoBut 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.