I have defined a struct, which has a constructor:
struct MyStruct
{
MyStruct(const int value)
: value(value)
{
}
int value;
};
and the following objects:
int main()
{
MyStruct a (true);
MyStruct b {true};
}
But I haven't received any compile errors, either with MVS2015 or Xcode 7.3.1.
bool
data, but after some time, code changed and bool
became int
and several bugs were introduced.)A bool
can be implicitly converted to an int
in a way that's value preserving. The only disallowed conversions with brace initialization are narrowing conversions (e.g. the reverse bool{42}
).
If you want to ensure that your class is constructible only with int
, then the direct way is simply to delete
all the other constructors:
struct MyStruct
{
explicit MyStruct(int i) : value(i) { }
template <typename T>
MyStruct(T t) = delete;
int value;
};
Here, MyStruct{true}
and MyStruct(false)
will yield calls to MyStruct::MyStruct<bool>
, which is defined as deleted and hence is ill-formed.
The advantage of this over static_assert
is that all the type traits will actually yield the correct values. For instance, std::is_constructible<MyStruct, bool>
is std::false_type
.
Here's a construction that allows you to only initialize your class from an int
value:
#include <type_traits>
struct MyStruct
{
template <typename T>
MyStruct(T t) : value(t)
{
static_assert(std::is_same<T, int>::value, "Bad!");
}
int value;
};
That's because the template argument deduction required by this constructor template will produce the exact type of the argument and not perform conversions, so you can perform tests on that type.
You should perhaps also or instead use SFINAE to constrain the constructor, so that MyStruct
doesn't present itself as constructible from anything.
Furthermore, you should probably also make the constructor template explicit
so that random integers don't become MyStruct
instances.
In other words, I'd write it like so:
struct MyStruct
{
template <typename T,
typename = std::enable_if_t<std::is_same<T, int>::value>>
MyStruct(T t) : value(t) {}
// ...
The simplest solution is to declare a bool constructor as deleted isn't it?
struct MyStruct
{
MyStruct(bool) = delete;
MyStruct(const int value)
: value(value)
{
}
int value;
};
example error output:
...
/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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With