如何将大于 std::numeric_limits<fundamental_type>::max() 的值传递给函数?
How to pass values greater than std::numeric_limits<fundamental_type>::max() to a function?
我正在编写一个函数 void func(K const& val)
,它是模板的一部分 class。
假设我将一个 class 对象定义为 foo<unsigned short int> f;
然后我将 func 调用为 f.func(999999);
发生的事情是值 999999
被转换为其他值,因为它本身超出了范围。我如何防止这种情况发生?代码中是否有编译器标志或其他方式可以防止这种情况发生?
正在检查
if(val > std::numeric_limits<K>::max())
在 func
内没有帮助,因为该值在传递时已经转换为数字限制内的值。
例如,999998989898988989999 转换为 11823
如何将大于 std::numeric_limits::max() 的值传递给函数?
P.S。我正在使用 gcc 进行编译(使用 -std=c++11)
假设您的 class foo
的定义类似于:
template<typename K>
class foo {
public:
void func(K const& k) {}
};
您可以制作 func
模板本身,并在调用实际实现之前检查限制:
#include <iostream>
#include <limits>
template<typename K>
class foo {
public:
template<typename T>
std::enable_if_t<std::is_signed<T>::value && !std::is_signed<K>::value> func(T const& t)
{
if (t < 0 || static_cast<std::make_unsigned_t<T>>(t) > std::numeric_limits<K>::max()) {
std::cout << "error\n";
return;
}
func_impl(t);
}
template<typename T>
std::enable_if_t<!std::is_signed<T>::value && std::is_signed<K>::value> func(T const& t)
{
if (t > static_cast<std::make_unsigned_t<K>>(std::numeric_limits<K>::max())) {
std::cout << "error\n";
return;
}
func_impl(t);
}
template<typename T>
std::enable_if_t<std::is_signed<T>::value == std::is_signed<K>::value> func(T const& k)
{
if (k < std::numeric_limits<K>::min() || k > std::numeric_limits<K>::max()) {
std::cout << "error\n";
return;
}
func_impl(k);
}
private:
void func_impl(K const& k)
{
std::cout << "normal\n";
}
};
int main()
{
foo<char>().func(127);
foo<char>().func(127u);
foo<char>().func(-128);
foo<char>().func(128);
foo<char>().func(128u);
foo<char>().func(-129);
foo<unsigned>().func(-1);
foo<int>().func(1u);
}
输出:
normal
normal
normal
error
error
error
error
normal
编辑
正如@BaumMitAugen 指出的那样,在我的 func
实现中,boost::numeric_cast 可能是手动 if
s 的更好替代方案 - 如果下溢或溢出,它将抛出异常发生并且您将避免大量最新编辑版本的代码样板,这些样板 (a) 有效并且 (b) 避免 signed/unsigned 比较警告。
我正在编写一个函数 void func(K const& val)
,它是模板的一部分 class。
假设我将一个 class 对象定义为 foo<unsigned short int> f;
然后我将 func 调用为 f.func(999999);
发生的事情是值 999999
被转换为其他值,因为它本身超出了范围。我如何防止这种情况发生?代码中是否有编译器标志或其他方式可以防止这种情况发生?
正在检查
if(val > std::numeric_limits<K>::max())
在 func
内没有帮助,因为该值在传递时已经转换为数字限制内的值。
例如,999998989898988989999 转换为 11823
如何将大于 std::numeric_limits::max() 的值传递给函数?
P.S。我正在使用 gcc 进行编译(使用 -std=c++11)
假设您的 class foo
的定义类似于:
template<typename K>
class foo {
public:
void func(K const& k) {}
};
您可以制作 func
模板本身,并在调用实际实现之前检查限制:
#include <iostream>
#include <limits>
template<typename K>
class foo {
public:
template<typename T>
std::enable_if_t<std::is_signed<T>::value && !std::is_signed<K>::value> func(T const& t)
{
if (t < 0 || static_cast<std::make_unsigned_t<T>>(t) > std::numeric_limits<K>::max()) {
std::cout << "error\n";
return;
}
func_impl(t);
}
template<typename T>
std::enable_if_t<!std::is_signed<T>::value && std::is_signed<K>::value> func(T const& t)
{
if (t > static_cast<std::make_unsigned_t<K>>(std::numeric_limits<K>::max())) {
std::cout << "error\n";
return;
}
func_impl(t);
}
template<typename T>
std::enable_if_t<std::is_signed<T>::value == std::is_signed<K>::value> func(T const& k)
{
if (k < std::numeric_limits<K>::min() || k > std::numeric_limits<K>::max()) {
std::cout << "error\n";
return;
}
func_impl(k);
}
private:
void func_impl(K const& k)
{
std::cout << "normal\n";
}
};
int main()
{
foo<char>().func(127);
foo<char>().func(127u);
foo<char>().func(-128);
foo<char>().func(128);
foo<char>().func(128u);
foo<char>().func(-129);
foo<unsigned>().func(-1);
foo<int>().func(1u);
}
输出:
normal
normal
normal
error
error
error
error
normal
编辑
正如@BaumMitAugen 指出的那样,在我的 func
实现中,boost::numeric_cast 可能是手动 if
s 的更好替代方案 - 如果下溢或溢出,它将抛出异常发生并且您将避免大量最新编辑版本的代码样板,这些样板 (a) 有效并且 (b) 避免 signed/unsigned 比较警告。