Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How is T(2) == T(1) different from std::is_same_v<T, bool> for integral type T?

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)

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>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).

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading