Question about enums with explicit enum-base

Hello,

it is great that clang is gaining new C++0x features so quickly! Even seemingly "smaller" innovations like
the possibility to explicitely specify the underlying type of an enum make programming in C++ easier.

So I was experimenting with <enum-base> and stumbled upon the following:

enum e: unsigned int { // (A)
//enum e: unsigned short { // (B)
  A,
  B,
  C
};

int main(int, char**)
{
  e a = A;
  return a > 0;
}

With line (A) active, the code compiles with clang r131844. With line (B) active, it results in: "use of
overloaded operator '>' is ambiguous (with operand types 'e' and 'int')". Followed by a long list of
built-in operators.

Now, FDIS 4.5p3 says that an enum types can be converted to its underlying type, in this case 'unsigned short'.
Furthermore, 5.9p2 says that "the usual arithmetic conversions" are performed for relational operators, i.e.
according to 5p9, for the enum above, the following is done:

1. Integral promotion to 'unsigned short' (4.5p3)
2. Conversion of 'unsigned short' to 'int' (5p9 item 5.4)

Judging from the error I got, though, it seems that clang does not perform the latter step. Is this the case
(and should I file a PR), or am I misreading the standard here?

Many thanks in advance,
Jonathan

Jonathan Sauer wrote:

Hello,

it is great that clang is gaining new C++0x features so quickly! Even
seemingly "smaller" innovations like the possibility to explicitely
specify the underlying type of an enum make programming in C++ easier.

So I was experimenting with <enum-base> and stumbled upon the following:

enum e: unsigned int { // (A)
//enum e: unsigned short { // (B)
  A,
  B,
  C
};

int main(int, char**)
{
  e a = A;
  return a > 0;
}

With line (A) active, the code compiles with clang r131844. With line (B)
active, it results in: "use of overloaded operator '>' is ambiguous (with
operand types 'e' and 'int')". Followed by a long list of built-in
operators.

Now, FDIS 4.5p3 says that an enum types can be converted to its underlying
type, in this case 'unsigned short'. Furthermore, 5.9p2 says that "the
usual arithmetic conversions" are performed for relational operators, i.e.
according to 5p9, for the enum above, the following is done:

1. Integral promotion to 'unsigned short' (4.5p3)
2. Conversion of 'unsigned short' to 'int' (5p9 item 5.4)

Judging from the error I got, though, it seems that clang does not perform
the latter step.

Integral promotions can promote your "a" to both "unsigned short" and "int",
because "unsigned short" can be further promoted to "int (assuming you are
not on a 16bit box, and have int 32bit).

5.9 is not active here, because first overload resolution is done with types
"e" and "int" against "operator>". There exist the candidate:

  >(int, int) // viable and best
  
That "operator>" was added by a set described as "operator>(L, R)", where
the pair "(L, R)" is the cartesian square of all promoted arithmetic types
(see 13.6p12 and 13.6p2 in the FDIS).

That one is better than all the others. The second parameter is an exact
match, and the first parameter is a promotion. For all other candidates, the
first parameter is either equally good (again "int") but then the second
parameter is not int (hence worse), or the first parameter is worse.

I can only guess that clang doesn't consider "e -> int" a promotion. Please
file a PR. Consider this, which fails too with clang:

enum e : unsigned short { };
void f(int); // should take this
void f(long);

int main() {
  e e1;
  f(e1);
}

Hello,

[...]
I can only guess that clang doesn't consider "e -> int" a promotion. Please
file a PR.

I filed PR9993 and included your example (I hope that's okay).

Thanks for your reply,
Jonathan