I would like to ensure that an integral type is not bool in static_assert. I found in the source code of libstdc++ that it uses _Mn(2) != _Mn(1) for this purpose:
template<typename _Mn, typename _Nn>
constexpr common_type_t<_Mn, _Nn>
gcd(_Mn __m, _Nn __n) noexcept
{
static_assert(is_integral_v<_Mn>, "std::gcd arguments must be integers");
static_assert(is_integral_v<_Nn>, "std::gcd arguments must be integers");
static_assert(_Mn(2) != _Mn(1), "std::gcd arguments must not be bool"); // HERE
static_assert(_Nn(2) != _Nn(1), "std::gcd arguments must not be bool");
using _Up = make_unsigned_t<common_type_t<_Mn, _Nn>>;
return __detail::__gcd(__detail::__absu<_Up>(__m),
__detail::__absu<_Up>(__n));
}
It seems that libstdc++ is intentionally avoiding the more apparent form !is_same_v<_Mn, bool>. How are the two forms different? Which one should I use for the same purpose?
@KamilCuk pointed out that _Mn(2) != _Mn(1) was once !is_same_v<remove_cv_t<_Mn>, bool> in libstdc++. (Commit)
>Solution :
There is only one type that passes the is_integral_v<_Mn> assert but would fail the _Mn(1) == _Mn(2) check, and that is bool. The check is ok to identify bool in this special circumstance, when only types that are std::integral_v == true are considered.
In general _Mn(1) == _Mn(2) is not sufficient to know that _Mn is bool. It could be any other type.
When you want to know if two types are the same you should use std::is_same.
PS: In general I do not advise to learn how to write C++ code from the implementation of the standard library. By no means it is bad code, but it is code that lives in a different domain. Most notably, things that are undefined in user code can be completely fine in the implementation (as for example identifiers like _Mn).