8

Sample unit:

struct Supercalifragilisticexpialidocious
{
    enum class Frob
    {
        Foo, Bar, Baz, Qux
    };

    Frob frob;
};

Supercalifragilisticexpialidocious maker();

void f()
{
    auto g = maker();

    // Allowed?
    if ( g.frob == g.Frob::Baz ) {}
}

This code is accepted by gcc 9.x and 10.x, but rejected by clang 10.x and 11.x (godbolt link) with an error like:

<source>:17:28: error: 'Supercalifragilisticexpialidocious::Frob::Baz' is not a member of class 'Supercalifragilisticexpialidocious'

My question is: is this code correct (i.e. is it just a clang bug?)


Background: I'd like to test g.frob == Supercalifragilisticexpialidocious::Frob::Baz but without having to repeat the classname. And in a more general situation where we obtained the object by auto, the classname might not immediately be obvious, or could be difficult due to templates.

I came up with the workaround of decltype(g)::Frob::Baz which seems to work in both compilers for the above code -- although if g were a reference, this is again accepted by gcc and rejected by clang.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • In MSVC, it compiles and runs, though Intellisense complains: `Supercalifragilisticexpialidocious::Frob::Baz is not a class member`. – Casey Mar 12 '21 at 03:11
  • @Casey I get the same in my gcc IDE -- which is because the IDE uses clang for intellisense – M.M Mar 12 '21 at 03:13
  • Yeah, I tend to ignore intellisense and only listen to the compiler. There were cases where MSVC's compiler team implemented newer features but the intellisense team didn't so it complained, but your code still worked. – Casey Mar 12 '21 at 03:17
  • In any case, `decltype` seems an appropriate workaround for not having to type a long typename. I use it in other contexts a lot because lazy. – Casey Mar 12 '21 at 03:18
  • In my real code `g` is actually a reference so the decltype workaround doesn't help – M.M Mar 12 '21 at 03:19
  • Can you put an example of that in your question? – Casey Mar 12 '21 at 03:20
  • I decided to stick to 1 question per question ... will post a follow-up depending on how this one is answered. (But just go `auto& h = g;` and try to do it on `h`) – M.M Mar 12 '21 at 03:20
  • `std::remove_reference_t::Frob::Baz` works – Casey Mar 12 '21 at 03:27
  • @Casey The cure is nearly worse than the problem – M.M Mar 12 '21 at 03:30
  • Although, if your class name is actually that long, you have some design issues you should look in to. :P – Casey Mar 12 '21 at 03:41

0 Answers0