Live data from Hacker News

Why should I have written ZeroMQ in C, not C++ (2012)

250bpm.com

101–110 of 170 posts

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#101

When I did C++ I always ended up using a very small subset of it. No exceptions, no inheritance besides a few interfaces. But in general I agree with his point. There are a few things C could improve though. One would be a way to automatically clean up resources. Maybe something like “defer” in Go. I wonder if templates would fit into C. STL is super useful. A real string type would be good too.

All the things you mentioned can be found in Zig! [1]

It's exception semantics are very similar to Go, but unlike Go, you have to handle the error. It has constructs like `defer` and `errdefer` which allow you do clean up at the end of the scope or on exception respectively. It has support for Generics and Metaprogramming without having to resort to preprocessor macros.

It just released v0.6.0 and is actively in development with an engaging and helpful community.[2]

[1]: https://ziglang.org/ [2]: https://github.com/ziglang/zig/wiki/Community

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#102
post #51

I think there's a lot of merit to this post, but it really shows its age. Modern C++ typically suffers from only the last point raised - exceptions during destruction, but that goes against the all good C++ practices. Overall, the author's approach to exception use is flawed. It's bad form to use exceptions for code flow purposes, as per their example. If you throw an exception in the same block that catches the exce…

A problem is if you use RAII for other resources than memory, for example files. You want to put the close function in the destructor then, but close can throw an exception. http://www.cplusplus.com/reference/fstream/ofstream/close/ (Of course the solution is easy, you wrap close in a try catch block, but as alwaya all the solutions are easy in c++ but this is one of the surprising corners, which might be done more o…

[deleted]

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#103
post #29
post #12

This article is simultaneously both obsolete and completely current. Obsolete in that the C++ committee has addressed almost all of the issues raised (e.g. constructor semantics, xception semantics et al) though the discussion of site-of-error/handling-of-error continues unabated. Later versions of C++ (17and 20) are powerful and expressive systems programming languages that aren’t like the object-oriented messes of…

I haven’t written anything nontrivial in C++ for many years and so far have only learned and used a couple minor features newer than C++11. Would you be kind enough to point to some resources on why C++17/20 are “powerful and expressive systems programming languages that aren’t like the object-oriented messes of old”?

I wrtote a reply to this question in a comment parallel to yours.

In addition:

I don't write many classes in the sense of the Gang of Four book. I do write classes that are really just ways to speak with the type system, e.g. a "class" that has one instance variable that is an integer, so takes up only as much space as a native int, yet perhaps acts a special kind of table index.

Sequence manipulation, auto, and destructuring bind provide clearer ways to express algorithms without getting hung up in towers of class abstraction (an evil fetish) yet not lots of low-level manipulation and boilerplate like you'd see with C.

In c++20 generics and templating are almost unified which makes expression so much clearer (most of the old templating syntax is unnecessary in most cases). It lets you manipulate the type system much more clearly. You can do a lot more at compiler time -- you'll never get the expressive power of the Lisp macro system, but it's a lot closer with a lot of the old syntactic junk discarded.

Auto declaration has transformed the use of the type system and genericity.

In terms of resources to learn this stuff: I haven't found any single good source of info for these revisions.

I once wrote a comment on this but it took a while and of course vanished into the whirlwind of YC comments. So instead I'll suggest a web search for "new in c++17" and "new in c++20". I know that's kind of lame, but that's the best high level answer I can suggest.

I will say www.cppreference.com is excellent, but when it comes to newer features you often need something a little higher level to really grok what it says. It might answer your specific question though.

I follow the trip reports from committee meetings and read proposals that happen to interest me which often give context to a design decision.

I started a new project (blank editor buffer) using C++-17 in 2016. I hadn't written c++ since around 2000 (though I'd previously been involved in g++ development since around '87.* So I treated it as if it were a brand new language I'd never seen before. The only book I bought was Stroustroup's "tour of C++" which introduced c++14, then used searches like the ones above to keep up with developments in C++.

If you're in the same boat I'd say choose C++20, even though the full language isn't available yet, which is what I did with C++17. Some features I was able to bring in from Boost (which is where many new features begin) and some I just couldn't use until it was time to refactor something anyway. Still, this really made a difference.

* yes before g++ was released by the FSF -- tiemann and I both worked at MCC at the time and used to have dinner at 3AM to discuss what each of us was working on, which is how we later came to start Cygnus.

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#104

Earlier quoted context omitted.

Another way to support RAII without throwing exceptions is to somehow make the error case an explicit configuration of the class with well-defined behavior. For example, in a "File" class with no filedescriptor you could return a defined "error" from any function calls which would require a filedescriptor. Receiving such a return value or return structure would then signal that the File class is not in a working stat…

yes. > when you cannot handle the error in the current code block and the function interface does not support returning enough information to the caller to detail what went wrong Exceptions are, fundamentally, an alternate way to return from a function. That's why the general practice is to avoid using them for control flow - there's enough in the language already to support what you want to do, we don't need to inst…

It should ultimately be a matter of readability. If it's more readable for you to use Exceptions, by all means use them. But if you're working in a domain where you have control over the type of the return, then choose a range of return values which contains a representation of all possible results of your function and not just the "everything is working" result to be explicit. You don't have to return only primitive types. You can return data structures too, so you can encode the error as part of a return type and treat it and the rest of the data on the same level.

In short, it's a little simplistic to go void->integer or void->boolean. You should really be going void->struct or void->class. That gives you wide latitude in defining the range of your output types.

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#105
post #96
post #29

Earlier quoted context omitted.

I haven’t written anything nontrivial in C++ for many years and so far have only learned and used a couple minor features newer than C++11. Would you be kind enough to point to some resources on why C++17/20 are “powerful and expressive systems programming languages that aren’t like the object-oriented messes of old”?

Yes, please.

Look for some parallel replies.

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#106
I believe the placement new operator does exactly what is needed here. It'll take a self-allocated block of memory and run the constructor on it, thereby avoiding the risk of system generated exceptions as execution stays purely in user code. Basically, it allows you to use a C++ constructor like a C init function.

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#107
post #77

The only thing I dislike about C++ is that I can't declare private fields privately, I can use private: but it is there in header... in C I can just declare struct Foo; in header then implement it without expose its gusts.

Are you familiar with the PIMPL idiom?

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#108

Earlier quoted context omitted.

Well, rarely done isn't the same as never done. docs.rs has exactly the tradeoffs the parent comment is talking about: we have a long-running daemon thread that uses `catch_unwind` and builder threads that occasionally panic. We've had [issues with memory leaks]( https://github.com/rust-lang/docs.rs/issues/656 ) in the past - they weren't related to unwinding that I know of, but it's still possible that they were. Ho…

> Well, rarely done isn't the same as never done. Absolutely. But I do think the difference between "idiomatic" and "rarely done" is valuable, here. And as you said yourself, it's not clear that these leaks are caused by this kind of thing. If someone saw Rust code leaking memory all the time due to catching panics, I'd want to know about it, because it's very contradictory to my own experience, and I think that's in…

Correct me if I'm wrong, but panics themselves are fairly rare.

That's not the case in C++ where "throw" is a keyword you are expected to use for error handling.

If you take this to a Java example, a panic is more like an "Error" and less like an "Exception". That is to say, in rust, if something panics it is a sign of a major bug that shouldn't have any option for recovery.

With all that said, the same concept exists in C++. Try doing a 1/0 in C++ and see what happens. You don't get some nice exception to catch and you can't add a "noexcept" clause to stop it from happening.

In the same original example, if you have that 1/0 error in the underlying method and you handle it instead of crashing by tying into the OS specific "div by zero" garbage. You to can create a memory leak in code thought to be safe.

It goes to show that you can't (and shouldn't) expect to recover from everything. Crashing, IMO, is usually far safer than trying to fix things up and move forward.

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#109

Earlier quoted context omitted.

> benchmarks have shown that exceptions are generally faster The blog post you linked to says "Immediately we see that once the stack depth grows above a certain size (here 200/3 = 66), exceptions are always faster. This is not very interesting, because call stacks are usually not this deep (enterprise Java notwithstanding). For lower depths there is a lot of noise, especially for GCC ..." So ... not exactly "general…

Look at all the results. Even before that exceptions are more often a win than a loss. > The same test on Windows/VC++ will probably run a lot slower ... By default on 32-bit, with SJLJ exceptions, that's likely. But on 64-bit windows the default exception handling (SEH) uses a similar mechanism than Linux and should have comparable performance.

I missed this in my previous reply ...

> Look at all the results. Even before that exceptions are more often a win than a loss.

The blog post you linked to effectively says "it depends"

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#110

Earlier quoted context omitted.

> Well, rarely done isn't the same as never done. Absolutely. But I do think the difference between "idiomatic" and "rarely done" is valuable, here. And as you said yourself, it's not clear that these leaks are caused by this kind of thing. If someone saw Rust code leaking memory all the time due to catching panics, I'd want to know about it, because it's very contradictory to my own experience, and I think that's in…

Correct me if I'm wrong, but panics themselves are fairly rare. That's not the case in C++ where "throw" is a keyword you are expected to use for error handling. If you take this to a Java example, a panic is more like an "Error" and less like an "Exception". That is to say, in rust, if something panics it is a sign of a major bug that shouldn't have any option for recovery. With all that said, the same concept exist…

Conceptually, panics should be rare, because one firing means that some sort of unexpected problem has occurred.

However, the real world is not "conceptually." I don't think there's any real data about how often they happen, but at least my experience is that tools I write in Rust rarely end up showing me panic output.

> That's not the case in C++ where "throw" is a keyword you are expected to use for error handling.

Yes, that's correct. The intended semantics of the two features are very, very different.

Post reply on HN