> If I remove both bool conversion operators, the compiler throws a tantrum about the if.
> Is that not compromising type-safety checks?
No, it is not. Compile-time type safety is compromised if and only if code that results in a type error (for instance, operations valid on an object of type
B
are performed on an incompatible object of type
A) is silently emitted. Needless to say, unless the programmer had explicitly instructed the compiler to remove the safety net by using a compile-time cast.
Run-time type safety is compromised if and only if code that results in a type error is executed.
The implicit conversion of a pointer/reference to a derived class object to a pointer/reference to the base class object does not compromise type safety.
An attempt at implicitly converting a pointer/reference to a base class object to a pointer/reference to a derived class object would have compromise compile-time type safety, had the compiler kept quiet about it
This C code is type-unsafe:
1 2 3 4 5 6 7 8 9 10
|
// *** C code ****
void c_function( int* pi )
{
if( pi != NULL )
{
double* pd = pi ; // compromises compile-time type safety
*pd += 7.8 ; // compromises run-time type safety
// ...
}
}
|
This C++ code is not. If any one of these constructs compromise type safety at compile-time, then all of them do. Obviously, none of these constructs compromise compile-time type safety.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
struct Lamborghini
{
operator bool() const { return false ; }
bool to_bool() const { return false ; }
explicit operator int() const { return 100 ; }
int foo() const { return 100 ; }
};
struct Pagani
{
operator bool() const { return false ; }
bool foo() const { return false ; }
explicit operator int() const { return 200 ; }
int to_int() const { return 200 ; }
};
int main()
{
if( Lamborghini() && Pagani() ) { /* ... */ }
if( Lamborghini() && bool( Pagani() ) ) { /* ... */ }
if( bool( Lamborghini() ) && bool( Pagani() ) ) { /* ... */ }
if( Lamborghini().operator bool() && Pagani().operator bool() ) { /* ... */ }
if( Lamborghini().to_bool() && bool( Pagani() ) ) { /* ... */ }
if( bool( Lamborghini() ) && Pagani().foo() ) { /* ... */ }
if( Lamborghini().to_bool() && Pagani().foo() ) { /* ... */ }
if( int( Lamborghini() ) < int( Pagani() ) ) { /* ... */ }
if( Lamborghini().foo() < Pagani().to_int() ) { /* ... */ }
if( int( Lamborghini() ) < int( Pagani() ) ) { /* ... */ }
if( Lamborghini().foo() < int( Pagani() ) ) { /* ... */ }
if( int( Lamborghini() ) < Pagani().to_int() ) { /* ... */ }
}
|