如何防止从 int 到无符号 int 的隐式转换
How to prevent implicit conversion from int to unsigned int?
>假设你有这个:
struct Foo {
Foo(unsigned int x) : x(x) {}
unsigned int x;
};
int main() {
Foo f = Foo(-1); // how to get a compiler error here?
std::cout << f.x << std::endl;
}
是否可以阻止隐式转换?
我能想到的唯一方法是显式提供一个构造函数,该构造函数采用int
并在int
为负时生成某种运行时错误,但如果我可以为此得到编译器错误会更好。
我几乎可以肯定,有一个重复项,但我能找到的最接近的是这个问题,而是问为什么允许隐式转换。
我对 C++11 和 C++11 之前的解决方案都感兴趣,最好是同时适用于两者的解决方案。
统一初始化可防止缩小范围。
它遵循一个(根据要求不起作用)示例:
struct Foo {
explicit Foo(unsigned int x) : x(x) {}
unsigned int x;
};
int main() {
Foo f = Foo{-1};
std::cout << f.x << std::endl;
}
只要尽可能习惯使用统一初始化(Foo{-1}
而不是Foo(-1)
)。
编辑
作为替代方案,正如 OP 在注释中要求的那样,也适用于 C++98 的解决方案是声明为private
构造函数获得int
(long int
等)。
实际上没有必要定义它们。
请注意,正如另一个答案中所建议的那样,= delete
也是一个很好的解决方案,但这也是自 C++11 以来的解决方案。
编辑 2
我想再添加一个解决方案,尽管它自 C++11 起有效。
这个想法是基于Voo的建议(有关更多详细信息,请参阅Brian的回应评论),并在构造函数的参数中使用SFINAE。
它遵循一个最小的工作示例:
#include<type_traits>
struct S {
template<class T, typename = typename std::enable_if<std::is_unsigned<T>::value>::type>
S(T t) { }
};
int main() {
S s1{42u};
// S s2{42}; // this doesn't work
// S s3{-1}; // this doesn't work
}
您可以通过删除不需要的重载来强制编译错误。
Foo(int x) = delete;
如果您希望在
每次出现此类代码时收到警告,并且您使用的是 GCC,请使用 -Wsign-conversion
选项。
foo.cc: In function ‘int main()’:
foo.cc:8:19: warning: negative integer implicitly converted to unsigned type [-Wsign-conversion]
Foo f = Foo(-1); // how to get a compiler error here?
^
如果需要错误,请使用 -Werror=sign-conversion
。
相关文章:
- 是否可以从int转换为enum类类型
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- 是什么导致了这种使用三进制而不是短整型的有符号int到无符号int转换
- 将字符串中的 int 转换为字母;
- 主.cpp:18:20:错误:从"int*"转换为"int"会失去精度 [-fa
- 将非常大的 int 转换为双倍,在某些计算机上会损失精度
- 如何将矢量<int>转换为字符数组?
- C++ 无法从 const int* 转换为 const_iterator
- 我不断收到错误 C2440'=':无法从"int *(__cdecl *)(int *,int *,int,int)"转换为"int *
- 如何将 int[4] 转换为 std::array<int,4>?
- 如何将data[i].int转换为vaible
- 将 int 转换为字符串,然后连接另一个变量以创建完整扩展名,然后将其转换为 const_char*
- 将私有矩阵形式 int 转换为双 C++
- 无法将参数 1 从 'int' 转换为 'int &'
- 将 int 转换为字符串后始终得到 0
- isspace 函数的性能警告,从 int 转换为布尔值
- 将大 int 转换为浮点数,而不舍入 c++
- 错误:无法将'uint8* {aka unsigned int*}'转换为"常量emxArray_uint8_T*"?
- 将未签名的INT转换为BCD
- 在 C++ 中将 int 转换为双精度