Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compiler error for conditional operator "?:" when used with typecasting operator

Following code is in simplest form:

struct X {
  operator char () const { return 'a'; }
};

int main ()
{
  X obj, *p = &obj;
  char a = *p;  // ok
  char c = (true)? *p : 'z';
}

This code gives compiler error as,

error: operands to ?: have different types ‘X’ and ‘char’

Why *p is not resolved to char when there is no ambiguity in class X for typecasting operator ? Is such spurious error message correct or it's a g++ bug ?

[Update Note: Interestingly this scenario doesn't generate such error]

like image 991
iammilind Avatar asked Nov 30 '11 10:11

iammilind


People also ask

What is conditional operator when do you use this operator?

The conditional operator (? :) is a ternary operator (it takes three operands). The conditional operator works as follows: The first operand is implicitly converted to bool . It is evaluated and all side effects are completed before continuing.

What is the C conditional operator?

The conditional operator in the C programming language The conditional operator can help you make decision-making statements in just a single line, where an if-else would take more than one line. The conditional operator takes three operands, so it is a ternary operator.

Which format is used for conditional operator?

The conditional (ternary) operator is the only JavaScript operator that takes three operands: a condition followed by a question mark ( ? ), then an expression to execute if the condition is truthy followed by a colon ( : ), and finally the expression to execute if the condition is falsy.

What is the use of conditional operators with example?

An Example of Conditional OperatorsThe conditional operator "&&" first evaluates whether its first operand (i.e., number % 2 == 0) is true and then evaluates whether its second operand (i.e., number % 4 == 0) is true. As both are true, the logical AND condition is true. Leahy, Paul.


2 Answers

It seems to be a compiler-bug. I checked it out in the spec, the Standard clearly says (§5.16/3 - C++03),

Otherwise, if the second and third operand have different types, and either has (possibly cv-qualified) class type, an attempt is made to convert each of those operands to the type of the other.

and the rest of the section explains how the conversion is done. There is nothing that stops *p from implicitly converting into char type, using the user-defined conversion operator.

Also, I compiled it with (GCC) 4.5.0. It gives no error, with -pedantic option as well. Tried it -std=c++98 and -std=c++0x. Still no error.

Most definitely, it is a compiler-bug.

like image 116
Nawaz Avatar answered Oct 27 '22 20:10

Nawaz


There are issues with implicit conversion between classes for the conditional operator ?: in certain versions of G++. Also depending on the version you may either see an error, or you may /not/ see such an errors, however all three of your samples are correctly flagged by G++.

This is less of an answer to the original question but a re-certification of the original poster's, and others', qualm that there might be problems with spurious errors with G++ compiler and the conversion behavior for class types as specified in ISOC++:2003 5.16/3 [expr.cond]/3 (also outlined above by @Nawaz)

One example that shows the converse of the original poster's sample where implicit conversion in both directions can happen but isn't flagged can be seen here.

I compiled this on G++ v3.4.6, v4.1.2, v4.2.1 and v4.5.0(windows) and saw no problems because as again @Nawaz said this is the correct behavior within the ISOC++:2003 spec.

However, when I followed the link on your IDEONE page the structure definition was different and that is the root of your error.

struct X
{
  char ch;
  X(const char c) : ch(c) {}

  operator char () const { return ch; }
};

int main ()
{
  X obj('a'), *p = &obj;
  char a = *p; // ok
  char c = (true)? *p : 'b';
}

Then as above the struct is different and I do get the error your see. This is a correct error as 'z' can be converted into X or char, and because of the constructor 'z' can also be converted into X - bi-directionality of X/'z' so the compiler should stop. However with a little change it can be made to pass and that is exactly the same bug as the GNU G++ bug posted above.

If you convert your sample above to a pointer sample it will fail. Character pointer, int pointer or whatever.

Although unrelated I thought it might be a good point to highlight something that often caught me out whilst cross-porting between Windows/Linux. MSVC will happily pass such conversions often if it deems the conversion to be "safe", or often it may proffer a warning that conversion is being done at the risk of loss of precision - I am not sure what the trigger for allowing this is.

like image 31
Lucien Murray-Pitts Avatar answered Oct 27 '22 22:10

Lucien Murray-Pitts