Search code examples
c++parametersnamed

Using Designated Initializer on member of inherited base class


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


Solution

  • 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
        };
    }