Strange compiler error with conditional operator

  • Thread starter Thread starter Mike Ruane-Torr
  • Start date Start date
M

Mike Ruane-Torr

Today's competition is to explain my compiler error. Here's the code:

enum RecType
{
Start,
// etc.
}

byte[] ret = new byte[17];
int pos = 0;
RecType Type;
..
..
..
ret[pos++] = (Type == RecType.Start ? 0x1 : 0x2); // ERROR

The error is:
"Cannot implicitly convert type 'int' to 'byte'"

What, even when the range of possible values can be determined at compile
time? Hmm...

Interestingly, the following compiles OK:
ret[pos++] = 0x2; // OK
 
ret[pos++] = (byte) ((Type==RecType.Start) ? 0x1 : 0x2);

Not with a compiler here, so if that doesn't work then:

ret[pos++] = ((Type==RecType.Start) ? ((byte) 0x1) : ((byte) 0x2));

Can you tell I like being explicit with my parens ;-)
 
ret[pos++] = (byte) ((Type==RecType.Start) ? 0x1 : 0x2);

Not with a compiler here, so if that doesn't work then:

ret[pos++] = ((Type==RecType.Start) ? ((byte) 0x1) : ((byte) 0x2));

Yes, I expect that works, and

ret[pos++] = (byte)((Type==RecType.Start) ? 0x1 : 0x2);

should probably work too. However, I think it's inconsistent with the
other example I gave, the one that compiles. Surely, whether the ?:
returns an int or a byte, it should still be able to assign it to a byte,
provided it knows the possible values?

I expect it's because the compiler knows that '0x2', for example, is a
single constant value, but it isn't clever enough to look at the two
constant values that are operands of the conditional operator and draw
useful conclusions about type-promotion.

Can you tell I like being explicit with my parens ;-)

Yes :)
 
Good day.

The reason is that overall conditional expression is not treated
as a constant expression. And value-dependent conversion correctness is
considered only if an expression being converted is a constant.

For example:

byte b = ( true ? 1 : 2 );

works ok, 'cause the expression is constant, so compiler checks that value 1
is in the range of 'byte', but

byte b = ( m()/* bool function */ ? 1 : 2 );

gives an error, 'cause compiler expects any integer value. Any integer is
not
implicitly convertable to 'byte'.

Best regards.
 
Good day.

The reason is that overall conditional expression is not treated
as a constant expression. And value-dependent conversion correctness is
considered only if an expression being converted is a constant.

For example:

byte b = ( true ? 1 : 2 );

works ok, 'cause the expression is constant, so compiler checks that
value 1
is in the range of 'byte', but

byte b = ( m()/* bool function */ ? 1 : 2 );

gives an error, 'cause compiler expects any integer value. Any integer is
not
implicitly convertable to 'byte'.

I see. I do understand this, but you must agree that in theory the
compiler could be made intelligent enough to spot that both arguments were
constants, and determine their common convertible type. One for the
wish-list...?
 
Back
Top