Reputation: 14184
I was answering this question, about the topic of user defined conversions to bool
and how to disable other conversions:
struct foo
{
operator bool() const //Explicit overload for bool
{
return true;
}
template<typename T>
operator T() const = delete; //Everithing which is not a bool (Everithing which
//does not fit in the explicit overload) would
//resolve to this operator and will fail.
};
int main()
{
foo f;
bool b = f; //OK
int i = f; //ERROR
char c = f; //ERROR
etc...
}
Later the OP asked me why conditionals like if( f == true )
failed (Where f
is a foo
. I have tried that by myself and that surprises me because that comparison with boolean literals leads to a conversion to int
(Which is disabled) instead of bool
:
int main()
{
foo f;
if( f ); //OK, converts to bool
if( f == true ); //ERROR: Conversion to int, which has been disabled
}
prog.cpp:20:12: error: use of deleted function ‘foo::operator T() const [with T = int]’ if( f == true);
..............................................................................................................................................^
My question is: Are boolean literals defined as integers (Like the common C macros #define true 1 #define false 0
), and if not, why that comparison lead to an int conversion instead of a bool
?
I'm using GCC4.8.1 with C++11 enabled ( -std=C++11
).
Here is an example of that behavior at ideone.
Upvotes: 4
Views: 1364
Reputation: 39151
Since foo
is a class type, special rules apply when using an operator that is not specifically defined for that class type, see [over.built]/12
For every pair of promoted arithmetic types
L
andR
, there exist candidate operator functions of the formLR operator*(L, R); LR operator/(L, R); LR operator+(L, R); LR operator-(L, R); bool operator<(L, R); bool operator>(L, R); bool operator<=(L, R); bool operator>=(L, R); bool operator==(L, R); bool operator!=(L, R);
where
LR
is the result of the usual arithmetic conversions between typesL
andR
.
Not the usage of the term promoted arithmetic types: This requires a promotion of bool
.
A bool
is promoted to an int
, see [conv.prom]/6 (integral promotions)
A prvalue of type bool can be converted to a prvalue of type
int
, withfalse
becoming zero andtrue
becoming one.
So there are candidate functions of the form
common_type<L,int> operator==(L, int);
where L
is a promoted arithmetic type. However, there are many of them, for example
common_type<int , int> operator==(int , int);
common_type<long , int> operator==(long , int);
common_type<long long, int> operator==(long long, int);
Each of which require a user-defined conversion from foo
to the promoted type. It is not clear to me why this isn't ambiguous, as foo
can be converted to any of them. This is also described in the open issue CWG 954.
If there are several non-template conversion functions, g++4.8.1 and clang++3.5 report this ambiguity. (It should be noted that clang might have a bug here, see this example which works fine with g++4.8.1.)
However, there is no candidate of the form
common_type<bool, int> operator==(bool, int);
as bool
is not a promoted arithmetic type. Therefore, the conversion from foo
to bool
will not be chosen for the expression
foo x;
x == true
Upvotes: 2
Reputation: 11502
Lets do a quick test here:
template <typename T>
struct OutputType;
int main()
{
OutputType<decltype(true)> a;
}
Atleast ideone outputs here that true
is of type bool
: http://ideone.com/Gm653T
However:
The type bool can be converted to int with the value false becoming 0 and true becoming 1.
Source: cppreference
And my guess is that exactly such a promotion happens here
Upvotes: 0
Reputation: 4184
Type bool is not #defined in C++. I'm thinking that the comparison promotes to int and requires the int conversion.
Upvotes: 0