This question is related to this question. The following code compiles fine VC9 compiler but gives the error when compied with Comeau online. Can anybody tell me which one is correct and what is the meaning of the error?
error: ambiguous "?" operation: second operand of type "TypesafeBool" can be converted to third operand typ开发者_运维问答e "bool", and vice versa TypesafeBool b = (1==1) ? f() : false;
class TypesafeBool
{
private:
bool m_bValue;
struct Bool_ {
int m_nValue;
};
typedef int Bool_::* bool_;
inline bool_ True() const { return &Bool_::m_nValue; }
inline bool_ False() const { return 0; }
public:
TypesafeBool( const bool bValue ) : m_bValue( bValue ){}
operator bool_() const { return m_bValue ? True() : False(); }
};
TypesafeBool f()
{
return TypesafeBool(true);
}
int main()
{
TypesafeBool b = (1==1) ? f() : false;
}
The error is that the ternary operator must have a single type, and your expression (1=1) ? f() : false
has two types -- f()
has type TypesafeBool
and false
has type bool
. You can convert between them, but Comeau doesn't know which you want to use. To resolve it, cast one of the sides of the ternary to the type of the other: (1=1) ? f() : TypesafeBool(false)
.
Comeau is correct here, as while it's obvious to the observer what type the result should take, the ternary expression needs to have a single type on its own, without reference to what it's used in, and the type it should pick is ambiguous.
Both cases for operator? result must have the same type. The natural type for them is TypesafeBool and bool. As there is an implicit conversion from bool to TypesafeBool and from bool to TypesafeBool, there is an ambiguity which should be applied.
C++ rules prevent the fact that the result is then used in a context where a TypesafeBool is expected or the fact that the result is known to be taken into account to prefer the second way
TypesafeBool b = (1 == 1)? f() : TypesafeBool(false);
should work.
To follow on from @hype's comment, this article also puts forward the same idea but with the constructor marked explicit
. This removes your ambiguity.
Note that your example would then work fine provided you change the initialisation of b
to
TypesafeBool b( (1==1) ? f() : false );
since the =
syntax is not allowed to invoke TypesafeBool( bool )
when it's marked explicit (because it's technically a composition of two constructors).
精彩评论