我已经定义了一个结构,它有一个构造函数:
struct MyStruct
{
MyStruct(const int value)
: value(value)
{
}
int value;
};
Run Code Online (Sandbox Code Playgroud)
和以下对象:
int main()
{
MyStruct a (true);
MyStruct b {true};
}
Run Code Online (Sandbox Code Playgroud)
但是我没有收到任何编译错误,无论是MVS2015还是Xcode 7.3.1.
bool数据,但一段时间后,代码改变,bool变得int和介绍了几个错误.)Bar*_*rry 72
A bool可以以int保留值的方式隐式转换为a.使用大括号初始化的唯一不允许的转换是缩小转换(例如反向bool{42}).
如果你想确保你的类只能用于构造int,那么直接的方法就是对delete所有其他构造函数:
struct MyStruct
{
explicit MyStruct(int i) : value(i) { }
template <typename T>
MyStruct(T t) = delete;
int value;
};
Run Code Online (Sandbox Code Playgroud)
在这里,MyStruct{true}并且MyStruct(false)将产生调用MyStruct::MyStruct<bool>,其被定义为已删除,因此是不正确的.
这种优势的好处static_assert是所有类型特征实际上都会产生正确的值.例如,std::is_constructible<MyStruct, bool>是std::false_type.
Ker*_* SB 15
这是一种结构,允许您只从一个int值初始化您的类:
#include <type_traits>
struct MyStruct
{
template <typename T>
MyStruct(T t) : value(t)
{
static_assert(std::is_same<T, int>::value, "Bad!");
}
int value;
};
Run Code Online (Sandbox Code Playgroud)
这是因为此构造函数模板所需的模板参数推导将生成参数的确切类型而不执行转换,因此您可以对该类型执行测试.
您或许也应该使用SFINAE来约束构造函数,这样MyStruct就不会将其自身表现为任何可构造的东西.
此外,您可能还应该创建构造函数模板,explicit以便随机整数不会成为MyStruct实例.
换句话说,我会这样写:
struct MyStruct
{
template <typename T,
typename = std::enable_if_t<std::is_same<T, int>::value>>
MyStruct(T t) : value(t) {}
// ...
Run Code Online (Sandbox Code Playgroud)
最简单的解决方案是声明一个bool构造函数,因为删除不是吗?
struct MyStruct
{
MyStruct(bool) = delete;
MyStruct(const int value)
: value(value)
{
}
int value;
};
Run Code Online (Sandbox Code Playgroud)
示例错误输出:
...
/Users/xxxxxxx/play/fast_return/skeleton/main.cpp:68:14: error: call to deleted constructor of 'MyStruct'
MyStruct b {true};
^ ~~~~~~
/Users/xxxxxxx/play/fast_return/skeleton/main.cpp:57:9: note: 'MyStruct' has been explicitly marked deleted here
MyStruct(bool) = delete;
^
2 errors generated.
Run Code Online (Sandbox Code Playgroud)