The C++ Core Guidelines has a narrow cast that throws if the cast changes the value. Looking at the microsoft implementation of the library:
//
This is checking for overflow. Lets look at
auto foo = narrow(std::numeric_limits::max())
T will be int and U will be unsigned int. So
T t = narrow_cast(u);
will give store -1 in t. When you cast that back in
if (static_cast(t) != u)
the -1 will convert back to std::numeric_limits so the check will pass. This isn't a valid cast though as std::numeric_limits overflows an int and is undefined behavior. So then we move on to
if (!details::is_same_signedness::value && ((t < T{}) != (u < U{})))
and since the signs aren't the same we evaluate
(t < T{}) != (u < U{})
which is
(-1 < 0) != (really_big_number < 0)
== true != false
== true
So we throw an exception. If we go even farther and wrap back around using so that t becomes a positive number then the second check will pass but the first one will fail since t would be positive and that cast back to the source type is still the same positive value which isn't equal to its original value.