C++ 20 में नामित इनिशियलाइज़र




aggregate c++20 (2)

मुझे c ++ 20 फीचर में से एक के बारे में एक प्रश्न मिला है, नामित इनिशियलाइज़र (इस फ़ीचर के बारे में अधिक जानकारी here )

#include <iostream>

constexpr unsigned DEFAULT_SALARY {10000};

struct Person
{
    std::string name{};
    std::string surname{};
    unsigned age{};
};

struct Employee : Person
{
    unsigned salary{DEFAULT_SALARY};
};

int main()
{
    std::cout << std::boolalpha << std::is_aggregate_v<Person> << '\n'; // true is printed
    std::cout << std::boolalpha << std::is_aggregate_v<Employee> << '\n'; // true is printed

    Person p{.name{"John"}, .surname{"Wick"}, .age{40}}; // it's ok
    Employee e1{.name{"John"}, .surname{"Wick"}, .age{40}, .salary{50000}}; // doesn't compile, WHY ?

    // For e2 compiler prints a warning "missing initializer for member 'Employee::<anonymous>' [-Wmissing-field-initializers]"
    Employee e2 {.salary{55000}}; 
}

इस कोड को gcc 9.2.0 और -Wall -Wextra -std=gnu++2a झंडे के साथ संकलित किया गया था।

जैसा कि आप ऊपर देख सकते हैं, दोनों संरचनाएं, Person और Employee समुच्चय हैं, लेकिन नामित संयोजकों का उपयोग करके Employee समुच्चय का प्रारंभ संभव नहीं है।

कोई मुझे समझा सकता है क्यों?


C ++ 20 मानक के अनुसार (9.3.1 समुच्चय। पृष्ठ # 3)

(३.१) - यदि इनिशियलाइज़र सूची निर्दिष्ट-इनिशियलाइज़र-लिस्ट है, तो एग्रीगेट क्लास के प्रकार का होगा, प्रत्येक डिज़ाइनर में पहचानकर्ता क्लास के एक डायरेक्ट नॉन-स्टैटिक डेटा मेंबर , और एग्रीगेट के स्पष्ट रूप से इनिशियलाइज्ड एलिमेंट्स का नाम रखेगा। वे तत्व हैं जो हैं, या हैं, वे सदस्य हैं।

इसलिए आप आधार वर्गों के डेटा सदस्यों को आरंभ करने के लिए नामित प्रारंभिक सूची का उपयोग नहीं कर सकते हैं।

इसके बजाय सामान्य सूची आरंभीकरण की तरह उपयोग करें

Employee e1{ "John", "Wick", 40, 50000 };

या

Employee e1{ { "John", "Wick", 40 }, 50000 };

या जैसा कि @ Jarod42 ने टिप्पणी में बताया है कि आप लिख सकते हैं

Employee e1{ { .name{"John"}, .surname{"Wick"}, .age{40} }, 50000 };

इस मामले में प्रत्यक्ष आधार वर्ग को एक निर्दिष्ट प्रारंभिक सूची द्वारा आरंभीकृत किया जाता है, जबकि पूरी तरह से वर्ग एम्प्लोय को गैर-नामित प्रारंभिक सूची द्वारा प्रारंभ किया जाता है।


आपके पास अलग-अलग ठिकानों से एक ही नाम के कई क्षेत्र हो सकते हैं,

इसलिए तार्किक रूप से, आपको वांछित आधार का नाम प्रदान करना चाहिए, लेकिन ऐसा लगता है कि ऐसा करने का कोई तरीका नहीं है।

// Invalid too:
Employee e1{.Person.name{"John"}, .Person.surname{"Wick"}, .Person.age{40}, .salary{50000}};
Employee e2{.Person{.name{"John"}, .surname{"Wick"}, .age{40}}, .salary{50000}};

इसके अलावा C ++ द्वारा निर्दिष्ट इनिशियलाइज़ेशन C की तुलना में अधिक विवश है:

नोट: आउट-ऑफ-ऑर्डर नामित इनिशियलाइज़ेशन, नेस्टेड इनिशियलाइज़ेशन, नेक्ड इनिशियलाइज़र्स और रेगुलर इनिशियलाइज़र्स का मिश्रण, और एरे के निर्दिष्ट इनिशियलाइज़ेशन सभी C प्रोग्रामिंग लैंग्वेज में समर्थित हैं, लेकिन C ++ में इसकी अनुमति नहीं है।







designated-initializer