4

I have the following struct MyStruct that calls Foo<int> on construction:

struct MyStruct {
    MyStruct() {
        Foo<int>();
    }

    template<typename T>
    void Foo() {
        []() {
            struct Base {
                Base(int n) {}
            };
            struct Derived : Base {
                // using Base=Base; // needs to be uncommented for Apple LLVM version 9.1.0 (clang-902.0.39.2)
                Derived() :
                    Base(0) // problematic line
                {}
            } derived;
        };
    }
};

I tried to compile this with clang (via godbolt, command line params --std=c++1y):

  • 3.6: error: type 'Base' is not a direct or virtual base of 'Derived' (see problematic line in code above)
  • 3.7 and newer: compiles (with a warning about unused expressions)

So I expected that with newer versions this should be ok. However, when I tried to compile it on a Mac using XCode9 (which, according to this, uses clang 4.0 (clang --version gives Apple LLVM version 9.1.0 (clang-902.0.39.2))), I get an error from the same line as issued by clang 3.6:

error: member initializer 'Base' does not name a non-static data member or base class

As a workaround, I tried introducing using Base=Base within struct Derived (as indicated), which made it compile via XCode. (As a sidenote: Using the same workaround did not work for clang 3.6 on godbolt.)

So here are my questions:

  • Is this a compiler bug? If yes: Is it documented somewhere?
  • Is my workaround using Base=Base valid, well-defined C++?
phimuemue
  • 34,669
  • 9
  • 84
  • 115
  • 1
    I do not see why the body of a lambda function should be treated any differently than the body of a non-lambda function. And since your inheritance is perfectly valid in a non-lambda function, what you describe looks like a bug to me. Moreover, if you add `static_assert(std::is_base_of::value,"Not base of");` in your lambda function, the compiler is just fine (tested with godbolt, clang 3.6, --std=c++1y). – vdavid Aug 29 '18 at 11:56
  • As for `using Base=Base;` it is exactly as if you wrote `typedef Base Base;` and the typedef-name is equivalent to the type without the `typedef` keyword. In other words, `Base` after the typedef (or using) is strictly the same as `Base` before typedef (or using). – vdavid Aug 29 '18 at 11:57
  • What does `explicit` do in the default constructor `explicit Derived()`? I've seen `explicit` used for single parameter constructors, but not for a default constructor and I'm intrigued (and my Google-fu has failed me). – Eljay Aug 29 '18 at 12:30
  • 1
    @Eljay See https://stackoverflow.com/questions/2836939/purpose-of-explicit-default-constructors for more information on `explicit`. For my example, it is redundant (was actually a leftover from my original problem). – phimuemue Aug 29 '18 at 12:43

0 Answers0