【发布时间】:2019-08-31 22:07:45
【问题描述】:
我尝试实现一个元函数来检查一个整数类型是否是另一个整数类型的子集。它应该独立于平台,并且至少可以与 C++ 标准定义的所有数字类型一起使用。我当前的实现有 5 个分支。我有两个问题。
- 我会错过任何案例吗?
- 是否需要第四个分支?
template <typename T1, typename T2>
constexpr bool is_subset(T1, T2)
{
if constexpr (std::is_same_v<T1, T2>)
{
return true;
}
if constexpr (std::is_same_v<T1, std::uintmax_t>)
{
return false;
}
else if constexpr (std::is_same_v<T1, std::intmax_t>)
{
return false;
}
else if constexpr (std::is_unsigned_v<T1> && std::is_unsigned_v<T2>)
{
return static_cast<std::uintmax_t>(std::numeric_limits<T1>::min()) >= static_cast<std::uintmax_t>(std::numeric_limits<T2>::min()) &&
static_cast<std::uintmax_t>(std::numeric_limits<T1>::max()) <= static_cast<std::uintmax_t>(std::numeric_limits<T2>::max())
}
else
{
return static_cast<std::intmax_t>(std::numeric_limits<T1>::min()) >= static_cast<std::intmax_t>(std::numeric_limits<T2>::min()) &&
static_cast<std::intmax_t>(std::numeric_limits<T1>::max()) <= static_cast<std::intmax_t>(std::numeric_limits<T2>::max())
}
}
修复了 intmax_t == long 的实现:
template <typename T1, typename T2>
constexpr bool is_subset2(T1, T2) noexcept
{
if constexpr (sizeof(T1) == sizeof(T2) && std::is_signed_v<T1> == std::is_signed_v<T2>)
{
return true;
}
else if constexpr (sizeof(T1) == sizeof(std::intmax_t))
{
return false;
}
else if constexpr (std::is_unsigned_v<T1> && std::is_unsigned_v<T2>)
{
return static_cast<std::uintmax_t>(std::numeric_limits<T1>::min()) >= static_cast<std::uintmax_t>(std::numeric_limits<T2>::min()) &&
static_cast<std::uintmax_t>(std::numeric_limits<T1>::max()) <= static_cast<std::uintmax_t>(std::numeric_limits<T2>::max());
}
else
{
return static_cast<std::intmax_t>(std::numeric_limits<T1>::min()) >= static_cast<std::intmax_t>(std::numeric_limits<T2>::min()) &&
static_cast<std::intmax_t>(std::numeric_limits<T1>::max()) <= static_cast<std::intmax_t>(std::numeric_limits<T2>::max());
}
}
【问题讨论】:
-
只有整数,包括字符。 T1 的所有值都必须是有效值 T2。
-
is_subset<long, long long>(0L, 0LL)在std::numeric_limits<long>::max() == std::numeric_limits<long long>::max()和std::is_same_v<long, std::intmax_t>的许多平台上失败。 -
我明白了。那不是bug吗?对于较新的编译器是否如此?
-
不,许多 64 位架构都这样做。 Example for the common x86-64
-
@MartinFehrs 请使用
@标记人员,以便他们收到通知。并且您当前的实现可以正常工作,只是因为您很幸运。如果这两种类型具有不同的符号和不同的大小,那么它将跳转到最后一种情况。如果无符号类型是uintmax_t,那么它将被转换为intmax_t,这会导致错误的最小和最大限制
标签: c++ templates predicate numeric-limits