是否有可能在编译时测试类型是否支持C++中的负零?

ant*_*rds 8 c++ signed types type-traits negative-zero

有没有办法写一个类型特征来确定一个类型是否支持C++中的负零(包括整数表示,如符号和大小)?我没有看到任何直接这样做的东西,并且std::signbit似乎不是constexpr.

澄清:我问,因为我想知道这是否可能,无论用例是什么,如果有的话.

Mic*_*ler 2

最好的办法就是在编译时排除有符号零的可能性,但永远不要在编译时完全肯定它的存在。C++ 标准在很大程度上避免了在编译时检查二进制表示形式:

  • reinterpret_cast<char*>(&value)被禁止在constexpr.
  • 也禁止使用union类型来规避上述规则。constexpr
  • 根据 C++ 标准,对整数类型的零和负零的操作行为完全相同,无法区分。
  • 对于浮点运算,常量表达式中禁止除以零,因此1/0.0 != 1/-0.0无法进行测试。

唯一可以测试的是整数类型的域是否足够密集以排除有符号零:

template<typename T>
constexpr bool test_possible_signed_zero()
{
    using limits = std::numeric_limits<T>;
    if constexpr (std::is_fundamental_v<T> &&
           limits::is_exact &&
           limits::is_integer) {
        auto low = limits::min();
        auto high = limits::max();
        T carry = 1;
        // This is one of the simplest ways to check that
        // the max() - min() + 1 == 2 ** bits
        // without stepping out into undefined behavior.
        for (auto bits = limits::digits ; bits > 0 ; --bits) {
            auto adder = low % 2 + high %2 + carry;
            if (adder % 2 != 0) return true;
            carry = adder / 2;
            low /= 2;
            high /= 2;
        }
        return false;
    } else {
        return true;
    }
}

template <typename T>
class is_possible_signed_zero:
 public std::integral_constant<bool, test_possible_signed_zero<T>()>
{};
template <typename T>
constexpr bool is_possible_signed_zero_v = is_possible_signed_zero<T>::value;
Run Code Online (Sandbox Code Playgroud)

仅保证如果此特征返回 false,则不可能有符号零。这个保证很弱,但我看不出有什么更强的保证。此外,它对浮点类型没有任何建设性的说明。我找不到任何合理的方法来测试浮点类型。