I have a following example (with overly safe boolean type):
#include <cstdlib>
struct boolean_type
{
explicit
boolean_type(bool _value)
: value_(_value)
{ ; }
explicit
operator bool () const
{
return value_;
}
private :
bool value_;
};
struct A
{
A(int const _i)
: i_(_i)
{ ; }
boolean_type operator == (A const & _other) const
{
return (i_ == _other.i_);
}
private :
int i_;
};
bool t()
{
return A(0) == A(0);
}
int main()
{
return EXIT_SUCCESS;
}
It is well-known that such code containing an errors: "could not convert '(((int)((const A*)this)->A::i_) == ((int) other.A::i ))' from 'bool' to 'boolean_type'" in return statement of bool A::operator == (A const &) const
and "cannot convert 'boolean_type' to 'bool'" in return statement of bool t()
. But what the risk here? Why there are not explicit conversion here in both cases? Why are implicit? In fact we explicitly specify the returning type bool
in second case and static_assert(std::is_same< bool, decltype(std::declval< int >() == std::declval< int >()) >::value, "!");
as such!
Additionally want to say:
Due to the specified obstruction I cannot simply replace all entries of the bool
to my super-safe boolean_type
(which is mocked-object ) in my user code, because, say, in return statement of boost::variant::operator ==
uses above construction, that treats there as implicit conversion . Similar obstructions are not unique.
You have two implicit conversions. One here:
return (i_ == _other.i_);
And another here:
return A(0) == A(0);
These are implicit because you are not explicitly telling the compiler that you want to convert the result of the comparisons to boolean_type
and bool
respectively. These implicit conversions are not allowed because you made both the constructor and conversion operator of boolean_type
explicit
- that's the whole point of the explicit
keyword.
You would need to do:
return static_cast<boolean_type>(i_ == _other.i_);
And:
return static_cast<bool>(A(0) == A(0));
The typical reason for making conversions to bool
explicit is because the conversion may be used in situations that you did not intend it to be used. For example, if you had boolean_type
objects called b1
and b2
with non- explicit
conversions, you would be able to do the following:
b1 > 0
b1 == b2
These are probably not the intended uses of the boolean conversion operator.
Why there are not explicit conversion here in both cases?
Because the onus is on you , the programmer, to be explicit if you want an explicit conversion.
Implicit conversions would work in this case if you had allowed them. But you didn't allow them when you marked operator bool
and boolean_type::boolean_type
as explicit
.
Why are implicit?
Because you did not write the conversion. You must:
boolean_type operator == (A const & _other) const
{
return boolean_type (i_ == _other.i_);
}
...and:
bool t()
{
return (bool) (A(0) == A(0));
}
But what the risk here?
You tell us. explicit
exists specifically to tell the compiler that there might be a risk in permitting some implicit conversions to take place. So when you marked those functions as explicit
you said to the compiler:
Ok, if you allow an implicit conversion from a bool to a boolean_operator or vice versa, something bad might happen. So don't allow those implicit conversions.
You didn't tell the compiler (or us) why those implicit conversions are dangerous. You only said that they were .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.