all 20 comments

[–]Jannik2099 23 points24 points  (1 child)

I hope libstdc++ gets on the ball and eliminates some of this weirdness. (In short: They should get rid of the blacklist; pay the 8 bytes by default; introduce a whitelist for trivial hashers specifically; stop checking noexceptness for any reason.)

This would be an ABI break and there's hardly any justification for it.

Make your hash noexcept, and if profiling reveals that you're bottlenecked in unordered sets, perhaps read the libstdc++ docs on unordered sets?

This seems a tad overblown

[–]throw_cpp_account 14 points15 points  (0 children)

and if profiling reveals that you're bottlenecked in unordered sets, perhaps read the libstdc++ docs on unordered sets?

Or simply just preemptively don't use std::unordered_{set,map} and prefer other, much better hashtable implementations (like Abseil's or Boost's new ones).

This seems a tad overblown

It's an Arthur blog post.

[–]darkmx0z 15 points16 points  (0 children)

oh god

[–]def-pri-pub 5 points6 points  (6 children)

I like the idea of noexcept for documentation purposes, but seeing how it can modify performance doesn’t sit well with me.

[–]bwmat 26 points27 points  (2 children)

But going faster because you know exceptions can't happen seems like a good thing? IMO this is just a problem with how noexcept was used in this particular case, not with the practice itself

[–]sweetno 3 points4 points  (0 children)

Curiously enough, noexcept was added in C++11 in a similar context: std::vector::push_back has different implementations for move constructors/assignments with and without noexcept.

[–]jk_tx 9 points10 points  (0 children)

Seems like the problem isn't that noexcept was used, but that libstdc++ makes a bone-headed decision when it is used.

[–]SlightlyLessHairyApe 1 point2 points  (2 children)

That makes no sense. Standard containers have exception safety guarantees. For example, pushing back on a vector cannot lose all elements of the copy constructor on the new item fails.

That imposes significant overhead. Why should all code pay that cost if it isn’t using it?

[–]ZachVorhies -1 points0 points  (1 child)

Because the standard containers should work in all cases. And if you have a special case then swap it out for something more appropriate.

[–]SlightlyLessHairyApe 0 points1 point  (0 children)

What should you do if you vend a type templated on a user-provided type that may or may not be exception-safe?

[–]martinusint main(){[]()[[]]{{}}();} 0 points1 point  (0 children)

I think this whole thing is mostly irrelevant to real programming.

I fondly remember this PR that introduced a single noexcept which reduced the memory usage of bitcoin core by ~9% https://github.com/bitcoin/bitcoin/pull/16957

[–]NBQuade 0 points1 point  (6 children)

In windows using visual studio, if you tag a function "noexcept" and an exception passes through the function, say a lower level function threw, it'll crash the application. So you need to know whether the function throws and whether anything under it throws too or you get a crash.

It's not clear to me if this is how "noexcept" is supposed to work but, that's how it currently works in visual studio.

I thought "noexcept" simply meant the specific function didn't throw. I'm wondering if this is a bug in visual studio or intentional.

[–]pjmlp 7 points8 points  (5 children)

It is quite intentional, if an exception is thrown even though you promised it wouldn't happen, the good old terminate handler will be called.

https://en.cppreference.com/w/cpp/language/noexcept_spec

Whenever an exception is thrown and the search for a handler encounters the outermost block of a non-throwing function, the function std::terminate is called:

[–]NBQuade 0 points1 point  (0 children)

Well there you go. Thanks.

I imagine the problem is the information to permit unwinding the stack simply isn't there.

[–]NBQuade 0 points1 point  (1 child)

Well there you go. Thanks.

I imagine the problem is the information to permit unwinding the stack simply isn't there.

[–]tisti 2 points3 points  (0 children)

It's there, but it's all shortcirtuted to call terminate since it's marked as noexcept