4

I created a class Something which holds a member variable.

I am able to do this, which works as intended:

struct Something
{
    bool Works;
};

int main()
{
    Something s = {
        .Works = false,
    };
}

Now, I want to created a struct inherited from Something, named Something2, and want to do the same thing, but I want to be able to have access to Something::Works (which I renamed DoesntWork, since it doesn't work!):

struct Something
{
    bool DoesntWork;
};

struct Something2 : public Something
{
    bool Works;
};


int main()
{
    Something2 s2 = {
        .Works = true,
        .DoesntWork = false,
    };
}

https://godbolt.org/z/rYT3br467

I am not looking for an alternative, I can already think of some. I am only wondering if this is possible, and if yes then how.

If it is not possible, I would really like to know the low-level reason, so don't hesitate!

UPDATE: Thanks to Nathan Oliver's comment, you can read: Designated initializers in C++20

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Nox
  • 713
  • 7
  • 16

2 Answers2

4

C++ is much stricter when it comes to designated initializers than C.

cppreference:

out-of-order designated initialization, nested designated initialization, mixing of designated initializers and regular initializers, and designated initialization of arrays are all supported in the C programming language, but are not allowed in C++.

C doesn't have the inheritance concept at all which makes C's version of designating (at least untill C++20) impossible. One possible, future, version would be to designate it "forward" as often done in constructors with delegating constructors. In that case, I'd expect the proper initialization to be this:

Something2 s2 = {
    Something = {
        .Works = false
    },
    .DoesntWorks = true
};

That's however not part of C++ as of C++20. You can however create constructors in C++ to accommodate (part of) your needs without designated initializers:

struct Something {
    bool DoesntWork;
};

struct Something2 : public Something {
    Something2(bool Doesnt, bool Does) : 
        Something{Doesnt}, 
        Works{Does} 
    {}
    bool Works;
};

int main() {
    Something2 s2
    {
        true, false
    }; 
}

or initialize each object without user defined constructors at all:

struct Something {
    bool DoesntWork;
};

struct Something2 : public Something {
    bool Works;
};

int main() {
    Something2 s2{
        // You could just make it `{true}` below, but mentioning the
        // subobject fits the purpose of a designated initializer for clarity:
        Something{true},
        // this must however be left unmentioned in C++20 since you can't
        // mix regular initializers with designated ones:
        false
    };
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
2

This works for me:

struct Something
{
    bool ThisWorks;
};

struct Something2 : Something
{
    bool Works;
};


int main()
{
    Something2 s2 = {
        { .ThisWorks = false },
        .Works = true
    };
}

Online Demo

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770