cplusplus / draft

C++ standards drafts
http://www.open-std.org/jtc1/sc22/wg21/
5.7k stars 751 forks source link

Incorrect example for member access expression with `using enum` in [enum.udecl] CWG2959 #7368

Open keinflue opened 1 week ago

keinflue commented 1 week ago

[enum.udecl]/2 contains this example:

enum class fruit { orange, apple };
struct S {
  using enum fruit;             // OK, introduces orange and apple into S
};
void f() {
  S s;
  s.orange;                     // OK, names fruit​::​orange
  S::orange;                    // OK, names fruit​::​orange
}

While it is correct that name lookup for orange in s.orange will find fruit::orange, the member access expression itself is not ok, because [expr.ref]/7.5 only specifies its behavior for member enumerators. using enum however doesn't make the enumerator a member enumerator ([class.mem.general]/3.5, [class.mem.general]/4).

Currently [expr.ref] simply lacks a statement about the behavior in this situation, but CWG issue 2902's proposed resolution would clarify that it is ill-formed.

From issue reported to Clang here.

zygoloid commented 1 week ago

To me it seems worth having CWG look at this to determine if accepting s.orange is intended and a non-editorial fix is preferred. Perhaps using enum fruit (and using fruit::orange;) should declare orange to be a member of class S? Though that has its own share of weirdness:

enum class fruit { orange };
struct S { using fruit::orange; } s;
auto a = s.S::orange; // OK?
auto b = s.fruit::orange; // OK?
struct T { using fruit::orange; } t;
auto c = s.T::orange; // OK?

(Treating using fruit::orange; as if it declares a new enumerator of the same type and with the same value as the original might address some of the surprising cases here. But might also introduce new problems with ambiguity if we end up with both the original and the new enumerator in a single lookup result.)

keinflue commented 5 days ago

I just noticed that the suggested resolution of CWG 2557 would make this well-formed again, but only if the enumerator is named with unqualified name.

So I agree it currently doesn't seem clear what the intended behavior should be.

jensmaurer commented 10 hours ago

CWG2959

zygoloid commented 5 hours ago

I just noticed that the suggested resolution of CWG 2557 would make this well-formed again, but only if the enumerator is named with unqualified name.

FWIW, the outcome we get from the suggested resolution of CWG2557 seems quite reasonable to me.