c++ 对于整型T,T(2)== T(1)与std::is_same_v〈T,bool>有何不同?

pdkcd3nj  于 2023-02-10  发布在  其他
关注(0)|答案(2)|浏览(208)

我想确保整型不是static_assert中的bool,我在libstdc++的源代码中发现它使用_Mn(2) != _Mn(1)来实现这个目的:

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));
    }

libstdc似乎有意地避免了更明显的形式!is_same_v<_Mn, bool>。这两种形式有什么不同?出于相同的目的,我应该使用哪种形式?
@KamilCuk指出,_Mn(2) != _Mn(1)在libstdc
中曾经是!is_same_v<remove_cv_t<_Mn>, bool>.(Commit

jobtbby3

jobtbby31#

只有一种类型通过is_integral_v<_Mn>Assert,但_Mn(1) == _Mn(2)检查失败,这就是bool。在这种特殊情况下,当只考虑std::integral_v == true类型时,检查可以识别bool
注意_Mn(1) == _Mn(2)可以检测和cv bool的变体,因此正确的比较是std::is_same_v<std::remove_cv_t<Mn>,bool>(感谢Jarod42指出这一点)。
然而,当不考虑仅std::integral_v == true时,_Mn(1) == _Mn(2)检查不足以知道它是否是bool,它可以是任何其他类型。
当你想知道两个类型是否相同时,你应该使用std::is_same
PS:一般来说,我不建议从标准库的实现中学习如何编写C++代码。这绝不是糟糕的代码,而是生活在不同领域中的代码。最值得注意的是,用户代码中未定义的东西在实现中可能完全没有问题(例如_Mn这样的标识符)。

vktxenjb

vktxenjb2#

事实证明,cv限定的非引用bool类型(const boolvolatile boolconst volatile bool)将通过std::is_integral_v<T> && !std::is_same_v<T, bool>,但无法通过std::is_integral_v<T> && T(2) == T(1)。应该使用std::remove_cv_t<T>而不是std::is_same_v中的T来正确处理这些类型。

相关问题