Error when using in-class initialization of non-static data member and nested class constructor

Solution 1:

Is this code really incorrect or are the compilers wrong?

Well, neither. The standard has a defect -- it says both that A is considered complete while parsing the initializer for B::i, and that B::B() (which uses the initializer for B::i) can be used within the definition of A. That's clearly cyclic. Consider this:

struct A {
  struct B {
    int i = (A(), 0);
  };
  A() noexcept(!noexcept(B()));
};

This has a contradiction: B::B() is implicitly noexcept iff A() does not throw, and A() does not throw iff B::B() is not noexcept. There are a number of other cycles and contradictions in this area.

This is tracked by core issues 1360 and 1397. Note in particular this note in core issue 1397:

Perhaps the best way of addressing this would be to make it ill-formed for a non-static data member initializer to use a defaulted constructor of its class.

That's a special case of the rule that I implemented in Clang to resolve this issue. Clang's rule is that a defaulted default constructor for a class cannot be used before the non-static data member initializers for that class are parsed. Hence Clang issues a diagnostic here:

    A(const B& _b = B())
                    ^

... because Clang parses default arguments before it parses default initializers, and this default argument would require B's default initializers to have already been parsed (in order to implicitly define B::B()).