From: Ike Naar on
The code below shows different behaviour with different compilers,
and I wonder which behaviour is the right one.
There's a struct X that has conversion operators to bool and to double,
Instances of this struct are used in a boolean context.
The idea is that the X instances are implicitly converted to bool.

/* code starts here */

#include <iostream>

struct X
{
X(int id) : m_id(id) {}
operator bool() const { std::cout << m_id << ":bool\n"; return false; }
operator double() const { std::cout << m_id << ":double\n"; return 0.0; }
int m_id;
};

int main()
{
X x0(0), x1(1);
bool b = x0 || x1; /* line 14 */
return b;
}

/* code ends here */

GNU C++ compiles it without warnings, and the run-time output is:
0:bool
1:bool

Sun C++ 5.9 compiles it without warnings, and the run-time output is:
0:double
1:double

Sun C++ 5.6 gives the following compilation errors:
"a.cpp", line 14: Error: Overloading ambiguity between
"X::operator bool() const" and "X::operator double() const".
"a.cpp", line 14: Error: Overloading ambiguity between
"X::operator bool() const" and "X::operator double() const".

The GNU C++ behaviour (implicit conversion to bool) is what I had expected,
and the Sun C++ behaviour came a bit as a surprise.

If the conversions are made explicit:

bool b = bool(x0) || bool(x1); /* line 14 */

then all three compilers behave as expected, so that would solve the
ambiguity, but still I'm wondering whether the original code has well-defined
behaviour, and, if so, which compiler is doing the right thing?

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Ian Collins on
On 07/ 8/10 03:57 PM, Ike Naar wrote:
> The code below shows different behaviour with different compilers,
> and I wonder which behaviour is the right one.
> There's a struct X that has conversion operators to bool and to double,
> Instances of this struct are used in a boolean context.
> The idea is that the X instances are implicitly converted to bool.
>
> /* code starts here */
>
> #include<iostream>
>
> struct X
> {
> X(int id) : m_id(id) {}
> operator bool() const { std::cout<< m_id<< ":bool\n"; return false; }
> operator double() const { std::cout<< m_id<< ":double\n"; return 0.0; }
> int m_id;
> };
>
> int main()
> {
> X x0(0), x1(1);
> bool b = x0 || x1; /* line 14 */
> return b;
> }
>
> /* code ends here */
>
> GNU C++ compiles it without warnings, and the run-time output is:
> 0:bool
> 1:bool
>
> Sun C++ 5.9 compiles it without warnings, and the run-time output is:
> 0:double
> 1:double

Sun C++ 5.10 compiles it without warnings, and the run-time output is
the same as g++.

> Sun C++ 5.6 gives the following compilation errors:
> "a.cpp", line 14: Error: Overloading ambiguity between
> "X::operator bool() const" and "X::operator double() const".
> "a.cpp", line 14: Error: Overloading ambiguity between
> "X::operator bool() const" and "X::operator double() const".
>
> The GNU C++ behaviour (implicit conversion to bool) is what I had expected,
> and the Sun C++ behaviour came a bit as a surprise.

It's probably a bug in the older compiler. A search of the bugs listed
in compiler patches or the compiler forum might show the issue.

--
Ian Collins

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Daniel Krügler on
On 8 Jul., 05:57, i...(a)localhost.claranet.nl (Ike Naar) wrote:
> The code below shows different behaviour with different compilers,
> and I wonder which behaviour is the right one.
> There's a struct X that has conversion operators to bool and to double,
> Instances of this struct are used in a boolean context.
> The idea is that the X instances are implicitly converted to bool.
>
> /* code starts here */
>
> #include <iostream>
>
> struct X
> {
> X(int id) : m_id(id) {}
> operator bool() const { std::cout << m_id << ":bool\n"; return false; }
> operator double() const { std::cout << m_id << ":double\n"; return 0.0; }
> int m_id;
> };
>
> int main()
> {
> X x0(0), x1(1);
> bool b = x0 || x1; /* line 14 */
> return b;
> }
>
> /* code ends here */

[..]

> Sun C++ 5.6 gives the following compilation errors:
> "a.cpp", line 14: Error: Overloading ambiguity between
> "X::operator bool() const" and "X::operator double() const".
> "a.cpp", line 14: Error: Overloading ambiguity between
> "X::operator bool() const" and "X::operator double() const".
>
> The GNU C++ behaviour (implicit conversion to bool) is what I had expected,
> and the Sun C++ behaviour came a bit as a surprise.
>
> If the conversions are made explicit:
>
> bool b = bool(x0) || bool(x1); /* line 14 */
>
> then all three compilers behave as expected, so that would solve the
> ambiguity, but still I'm wondering whether the original code has well-defined
> behaviour, and, if so, which compiler is doing the right thing?

I think that Sun C++ 5.6 does this incorrect. According to
[over.built]/26 the only relevant candidate operator function is

bool operator||(bool, bool);

and thus the conversion to bool is the only possible one.

It is correct that the current language has still some open
points in regard to built-in candidate operators, among those
problems with assignments:

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#260
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#507

and equality:

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#545
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#954

but I don't see how they could be related to your example.

HTH & Greetings from Bremen,

Daniel Kr�gler


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: litb on
On 8 Jul., 05:57, i...(a)localhost.claranet.nl (Ike Naar) wrote:
> The code below shows different behaviour with different compilers,
> and I wonder which behaviour is the right one.
> There's a struct X that has conversion operators to bool and to double,
> Instances of this struct are used in a boolean context.
> The idea is that the X instances are implicitly converted to bool.
>
> /* code starts here */
>
> #include <iostream>
>
> struct X
> {
> X(int id) : m_id(id) {}
> operator bool() const { std::cout << m_id << ":bool\n"; return false; }
> operator double() const { std::cout << m_id << ":double\n"; return 0.0; }
> int m_id;
>
> };
>
> int main()
> {
> X x0(0), x1(1);
> bool b = x0 || x1; /* line 14 */
> return b;
>
> }
>
> /* code ends here */
>
> GNU C++ compiles it without warnings, and the run-time output is:
> 0:bool
> 1:bool
>
> Sun C++ 5.9 compiles it without warnings, and the run-time output is:
> 0:double
> 1:double
>
> Sun C++ 5.6 gives the following compilation errors:
> "a.cpp", line 14: Error: Overloading ambiguity between
> "X::operator bool() const" and "X::operator double() const".
> "a.cpp", line 14: Error: Overloading ambiguity between
> "X::operator bool() const" and "X::operator double() const".
>
> The GNU C++ behaviour (implicit conversion to bool) is what I had expected,
> and the Sun C++ behaviour came a bit as a surprise.
>
> If the conversions are made explicit:
>
> bool b = bool(x0) || bool(x1); /* line 14 */
>
> then all three compilers behave as expected, so that would solve the
> ambiguity, but still I'm wondering whether the original code has well-defined
> behaviour, and, if so, which compiler is doing the right thing?
>

Overload resolution of the builtin operator is "operator||(bool,
bool)". Let's construct an equivalent situation

void f(bool);
void g() { X x0(0); f(x0); }

X can be converted to bool by using operator bool and operator double.
During overload resolution for the conversion functions, "operator
bool" is preferred over "operator double" (which could do the job too)
because bool->bool is better than double->bool. The user defined
conversion sequence is thus "X -> (operator bool) -> bool", for the
conversion "X -> bool", and there is no ambiguity. GCC is correct.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]