Home > front end >  Why can I use curly brackets to initialize one enum class with a value from another enum class?
Why can I use curly brackets to initialize one enum class with a value from another enum class?

Time:06-22

I have found the following behavior of Clang-12, Clang-13 and Clang-14 with c 17 standard:

enum class FOO {
  VALUE
};

enum class BAR {
  VALUE
};

FOO value1{BAR::VALUE}; // OK
FOO value2 = BAR::VALUE; // Error

Why is there a difference? I would expect enum class to be 100% type safe.

Compiler Explorer

CodePudding user response:

This is CWG issue 2374.

In C 17, before the resolution of this issue, direct-list-initialization of an enumeration with a fixed underlying type by a single expression was specified to always be equivalent to a functional style cast. A functional style cast then would be equivalent to a static_cast and that would actually be allowed between different enumeration types (by going through the promoted underlying type).

With the issue resolution this path is taken only if the initializer expression is implicitly convertible to the enumeration type, which doesn't allow for conversion between different enumeration types.

That seems to have been an oversight in the resolution of a prior issue for C 17: CWG 2251

It seems that Clang decided to faithfully implement CWG 2251 and only revert this special case once CWG 2374 was resolved, while GCC and MSVC decided to not implement CWG 2251 faithfully.

CodePudding user response:

Both of these produce compiler errors for me in VS2022 under C 17 and C 20.

GCC 9.3.0 on Ubuntu also produce compiler errors.

Perhaps this is a Clang-specific bug or extension? (Maybe Clang attempts to automatically cast when using bracket initialization?)

I was able to reproduce this behavior only when using Clang up to version 14.

Compiler error with Clang (trunk):

error: cannot initialize a variable of type 'FOO' with an rvalue of type 'BAR'
FOO value{BAR::VALUE};
          ^~~~~~~~~~
  • Related