Não é mais possível fazer postagens ou usar assinaturas novas da Usenet nos Grupos do Google. O conteúdo histórico continua disponível.
Dismiss

Incompatible types in conditional operator (?:)

545 visualizações
Pular para a primeira mensagem não lida

eca

não lida,
22 de abr. de 2010, 09:09:5422/04/2010
para
Hello,

Can anyone explain the reasons why using the ternary operator (?:) in
the following code is illegal?
It is not completely clear to me in what assignment to b_ok is
different from assignment to b_ko.
Thanks in advance,
eca

// CODE

class B {};
class D1 : public B {};
class D2 : public B {};

int main(int argc, char * argv[])
{
D1* d1 = 0;
D2* d2 = 0;

B* b_ok;
if (d1) b_ok = d1;
else b_ok = d2;

B* b_ko = (d1 ? d1 : d2);
}

// Results using Comeau Online:

Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for
ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 14: error: operand types are incompatible ("D1 *"
and "D2 *")
B* b_ko = (d1 ? d1 : d2);
^

"ComeauTest.c", line 10: warning: variable "b_ok" was set but never
used
B* b_ok;
^

1 error detected in the compilation of "ComeauTest.c".

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

Daniel Krügler

não lida,
22 de abr. de 2010, 19:19:2022/04/2010
para
On 22 Apr., 15:09, eca <enrico.ecam...@gmail.com> wrote:
> Hello,
>
> Can anyone explain the reasons why using the ternary operator (?:) in
> the following code is illegal?
> It is not completely clear to me in what assignment to b_ok is
> different from assignment to b_ko.
> Thanks in advance,
> eca
>
> // CODE
>
> class B {};
> class D1 : public B {};
> class D2 : public B {};
>
> int main(int argc, char * argv[])
> {
> D1* d1 = 0;
> D2* d2 = 0;
>
> B* b_ok;
> if (d1) b_ok = d1;
> else b_ok = d2;
>
> B* b_ko = (d1 ? d1 : d2);
> }

The semantics of the conditional operator is defined
in terms of interchangeable conversions of the second
and third operand. In your example the second operand
is of type D1* and the third one is of type D2*.
Referring to recent N3090 wording, [expr.cond]/3
bullet 3 subbullet 2 is the corresponding slot. Here we
find that either the second operand must convertible
to the third or vice verse, but none of these is true.
But you can satisfy the requirements, by up-casting
either of these operands to a base class pointer:

B* b_ko = (d1 ? (B*) d1 : d2);

HTH & Greetings from Bremen,

Daniel Krügler

Stuart Golodetz

não lida,
22 de abr. de 2010, 19:18:4422/04/2010
para

The types of the true and false parts of an expression using the ternary
operator have to be the same, and in your example they're not (D1* is
not the same as D2*). The fact that you're assigning the result to a B*
(and both D1* and D2* are convertible to B*) doesn't matter -- the
compiler needs to give a type to the expression "d1 ? d1 : d2", and it
can't unless d1 and d2 have the same type. If you were really keen to
write it using the ternary operator, you could do:

B *b_ko = d1 ? (B*)d1 : (B*)d2;

In that case, the type of the ternary expression is clear (B*).

Regards,
Stu

restor

não lida,
22 de abr. de 2010, 19:20:0122/04/2010
para

> Can anyone explain the reasons why using the ternary operator (?:) in
> the following code is illegal?
> It is not completely clear to me in what assignment to b_ok is
> different from assignment to b_ko.
> Thanks in advance,
> eca
>
> // CODE
>
> class B {};
> class D1 : public B {};
> class D2 : public B {};
>
> int main(int argc, char * argv[])
> {
> D1* d1 = 0;
> D2* d2 = 0;
>
> B* b_ok;
> if (d1) b_ok = d1;
> else b_ok = d2;
>
> B* b_ko = (d1 ? d1 : d2);
>
> }

Hi, this question has already been asked (and explained) recently in
this list. Have a look at:
http://groups.google.co.uk/group/comp.lang.c++.moderated/browse_thread/thread/1cd1f4e24d6734b6

In short, the conditional operator is for selecting two different
values of the same type, and not for finding a comon type of the two.
And although it sometimes does find conversions it is not its purpose.

Regards,
&rzej

Jens Schmidt

não lida,
22 de abr. de 2010, 19:20:4522/04/2010
para
eca wrote:

> Can anyone explain the reasons why using the ternary operator (?:) in
> the following code is illegal?

It is not the use of the ternary operator as such, but your choice
of operands that is illegal. The 2nd and 3rd operands have to be of
the same type or one of them has to be convertible into the other.
Neither of these requirements is fulfilled.

> It is not completely clear to me in what assignment to b_ok is
> different from assignment to b_ko.

The compiler doesn't know at the point of evaluation ?: that the
result will later be converted to B*. So do that before.

Necessary changes:


> B* b_ko = (d1 ? d1 : d2);

Use one of
B* b_ko = (d1 ? static_cast<B*>(d1) : d2);
B* b_ko = (d1 ? d1 : static_cast<B*>(d2));
B* b_ko = (d1 ? static_cast<B*>(d1) : static_cast<B*>(d2));

BTW, the same problem is about as old as C, with B, D1, and D2
replaced by int, float, and some enum, respectively.
--
Greetings,
Jens Schmidt

Vaclav Haisman

não lida,
22 de abr. de 2010, 19:23:3622/04/2010
para
There has to be a conversion from the type of the second expression to the
type of the third expression of the ternary operator, or the other way
around. Change the second expression to static_cast<B*>(d1) and it should work.

--
VH

Bo Persson

não lida,
22 de abr. de 2010, 19:21:2022/04/2010
para

The compiler is trying to determine the type of the result of the
ternary operator. It can only do that if d1 and d2 have the same type,
or one is convertible to the other.

The fact that they are both convertible to a common type is not
enough.


Bo Persson

Johannes Schaub (litb)

não lida,
22 de abr. de 2010, 19:21:4822/04/2010
para
eca wrote:

> Hello,
>
> Can anyone explain the reasons why using the ternary operator (?:) in
> the following code is illegal?
> It is not completely clear to me in what assignment to b_ok is
> different from assignment to b_ko.
> Thanks in advance,
> eca
>
> // CODE
>
> class B {};
> class D1 : public B {};
> class D2 : public B {};
>
> int main(int argc, char * argv[])
> {
> D1* d1 = 0;
> D2* d2 = 0;
>
> B* b_ok;
> if (d1) b_ok = d1;
> else b_ok = d2;
>
> B* b_ko = (d1 ? d1 : d2);
> }
>

It doesn't work like that. First, we need to analyze what type (d1 ? d1 :
d2)" has. And we won't find a common type. Neither D1* nor D2* fits the
bill. It won't try "B*" because it doesn'T see the request to use it.
Neither does it try "void*" or any other type both can be converted to.
Therefor you get an ambiguity.

Stuart Golodetz

não lida,
23 de abr. de 2010, 00:52:1823/04/2010
para

Looks like I missed the case of one of the types being convertible to the other :) My bad, sorry. The general point (that the compiler doesn't consider things to which both of the types might convert) is true, though.

Francis Glassborow

não lida,
23 de abr. de 2010, 08:57:3623/04/2010
para

That is more than is actually required. The second and third operand
must either be of the same type (as you state) or one must be
convertible into the other.

--

0 nova mensagem