检查数字类型是否是另一个的子集
Check if numeric type is subset of another
我尝试实现一个元函数来检查一个整数类型是否是另一个整数类型的子集。它应该是独立于平台的,并且至少适用于 C++ 标准定义的所有数字类型。我目前的实施有 5 个分支。我有两个问题。
- 我会遗漏任何案例吗?
- 第4个分支是必要的吗?
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());
}
}
我不知道为什么 std::uintmax_t
和 std::intmax_t
有不同的案例。我觉得可以简化为只有3种情况:
template <typename T1, typename T2>
constexpr bool is_subset2(T1, T2) noexcept
{
if constexpr (sizeof(T1) == sizeof(T2))
{
// true if both signed or both unsigned
return std::is_signed_v<T1> == std::is_signed_v<T2>;
}
else if constexpr (sizeof(T1) < sizeof(T2))
{
// true if both unsigned, or T2 is signed
return std::is_signed_v<T2> || std::is_unsigned_v<T1>;
}
else
{
return false;
}
}
我尝试实现一个元函数来检查一个整数类型是否是另一个整数类型的子集。它应该是独立于平台的,并且至少适用于 C++ 标准定义的所有数字类型。我目前的实施有 5 个分支。我有两个问题。
- 我会遗漏任何案例吗?
- 第4个分支是必要的吗?
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());
}
}
我不知道为什么 std::uintmax_t
和 std::intmax_t
有不同的案例。我觉得可以简化为只有3种情况:
template <typename T1, typename T2>
constexpr bool is_subset2(T1, T2) noexcept
{
if constexpr (sizeof(T1) == sizeof(T2))
{
// true if both signed or both unsigned
return std::is_signed_v<T1> == std::is_signed_v<T2>;
}
else if constexpr (sizeof(T1) < sizeof(T2))
{
// true if both unsigned, or T2 is signed
return std::is_signed_v<T2> || std::is_unsigned_v<T1>;
}
else
{
return false;
}
}