我有这个班级
struct foo
{
explicit foo(const std::uint32_t& x, const std::uint32_t& y);
};
和方法
int main()
{
std::int32_t x = -1;
std::int32_t y = -1;
foo f(x, y);
}
在我的编译器(MSVC2012)上,这将编译并运行包含无符号类型的值x
和y
。我没想到会这样,但由于类型不匹配而期待编译错误。
我错过了什么?
答案 0 :(得分:7)
你运气不好,标准确实允许通过为常量引用传递的参数创建匿名临时值,将signed隐式转换为unsigned。
(请注意,对于非常量引用,情况并非如此)。
如果您使用的是C ++ 11,最好的办法是使用
删除构造函数foo(const std::int32_t& x, const std::int32_t& y) = delete;
Pre C ++ 11你可以使这个构造函数private
而不是定义它。而不是老式的不可复制的习语。
MSVC2012是一种中途的C ++ 03 / C ++ 11编译器。它实现了一些C ++ 11功能,但没有实现其他功能。遗憾的是删除构造函数是不支持的功能之一,因此private
isation方法是您可以使用的最佳方法。
答案 1 :(得分:0)
实际上,您应该使用至少会发出警告的新大括号初始化语法foo f{x, y}
。之后,您可以将编译器配置为将警告视为错误并相应地处理它们,因为良好的代码通常也应该消除警告(因为如果您想要转换发生,您应该使用< strong>显性演员)。
答案 2 :(得分:0)
explicit
不会阻止使用构造函数参数进行隐式转换(这在绑定引用时明显发生);它可以防止隐式构建。
void bar(foo);
int main()
{
foo f({0, 0}); // doesn't matter that the arguments are implicitly converted
bar({0, 0}); // error - implicit conversion required here to pass a foo
bar(f); // crucially, ok because argument requires no conv. construction
}