Using Designated Initializer on member of inherited base class [duplicate]
Asked Answered
S

2

8

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

Salivate answered 7/6, 2022 at 19:14 Comment(4)
en.cppreference.com/w/cpp/language/…Daphnedaphnis
Thank you, I did not know how that was called and that answers the questionSalivate
No problem. Not knowing the terminology makes it really hard to search for.Daphnedaphnis
@Daphnedaphnis "Not knowing the terminology makes it really hard to search for" <- Me, searching for solutions to problems (I've decided are) in the math domain.Keble
K
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
    };
}
Keble answered 7/6, 2022 at 20:2 Comment(0)
M
1

This works for me:

struct Something
{
    bool ThisWorks;
};

struct Something2 : Something
{
    bool Works;
};


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

Online Demo

Madcap answered 7/6, 2022 at 20:5 Comment(3)
Only with complier extensions not turned off though.Keble
@TedLyngmo dang, OK. Didn't realize this was an extension. It was just the first logical thing I tried and it worked.Madcap
Yepp - me too :-)Keble

© 2022 - 2024 — McMap. All rights reserved.