एक वर्ग के पास U प्रकार की वस्तु है। एक विधि के माध्यम से यह इस ऑब्जेक्ट को एक गेटटर का उपयोग करके const U& के रूप में उजागर करता है (सस्ते में कॉपी करने योग्य नहीं, संशोधन वांछित नहीं है)।

एक ग्राहक, अब इस एपीआई का उपयोग करना चाहता है। वह एक जटिल वस्तु के हिस्से के रूप में U के उदाहरण का उपयोग करना चाहता है (जिसे एपीआई ऑब्जेक्ट को बदलने में कोई दिलचस्पी नहीं है)। इसलिए, उसके पास कम से कम निम्नलिखित विकल्प हैं: पैरामीटर के रूप में const U& के साथ एक वर्ग T बनाएं और const U& प्रकार का एक निजी क्षेत्र, जहां निर्माता एपीआई के उदाहरण को संग्रहीत करता है। इसका वर्ग के उदाहरणों को अत्यंत लचीला बनाने का अत्यधिक नुकसान है (उदाहरण के लिए std::vectors का उपयोग करके कोई प्रबंधन नहीं), जो वांछित नहीं है।

बहुत समय पहले नहीं, मैंने पाया कि कोई std::reference_wrapper<const U> का उपयोग const U& को स्टोर करने के लिए भी कर सकता है, जो T प्रकार के उदाहरणों पर उन नुकसानों को लागू नहीं करेगा।

अब प्रश्न यह है कि क्या यह वैसा व्यवहार करता है जैसा इसकी अपेक्षा की जाती है और क्या ऐसा करना एक अच्छा अभ्यास है?

निम्नलिखित और यहां में, आप इस रणनीति और वर्णित प्रकारों का उपयोग करके एक कार्यशील कोड पा सकते हैं।

#include <iostream>
#include <memory>

class U{
    public: 
    uint value;
};

class T{
private:
    std::reference_wrapper<const U> _u;

public:
    T(const U& u)
        :_u(u) {}

    const U& GetU(){
        return _u;
    }
};

const U& provideValue(U& u){
    return u;
}

int main()
{
    U internalApiValue;
    internalApiValue.value = 5;

    auto apiValue = provideValue(internalApiValue);

    T container(apiValue);

    std::cout << container.GetU().value;
}

मुझे लगता है कि अगर यह एक अच्छा विचार नहीं है, तो एकमात्र विकल्प कॉन्स्ट से बचना होगा, क्योंकि अन्यथा मैं इस तरह के तरीकों के उपयोगकर्ताओं पर उच्च प्रतिबंध लगाऊंगा (विधियां U& के बजाय const U& को उजागर करती हैं या U)?

0
JFFIGK 16 जिंदा 2019, 16:16

2 जवाब

सबसे बढ़िया उत्तर

यह वही करना चाहिए जो आप चाहते हैं। यह std::reference_wrapper<T> का उपयोग उस तरीके से कर रहा है जिस तरह से इसका उपयोग करने का इरादा था (संदर्भों को इस तरह से पास करना जो उन्हें कॉपी करने योग्य और असाइन करने योग्य बनाता है)। मुझे इसमें कुछ भी गलत नहीं दिखता। cppreference.com से:

std::reference_wrapper एक क्लास टेम्प्लेट है जो किसी संदर्भ को कॉपी करने योग्य, असाइन करने योग्य ऑब्जेक्ट में लपेटता है। इसे अक्सर मानक कंटेनरों (जैसे std::vector) के अंदर संदर्भों को संग्रहीत करने के लिए एक तंत्र के रूप में उपयोग किया जाता है जो सामान्य रूप से संदर्भ नहीं रख सकता है।

एकमात्र संभावित नकारात्मक पहलू यह है कि एक std::reference_wrapper<T> उपयोग करने के लिए थोड़ा अजीब हो सकता है और कुछ के लिए अपरिचित हो सकता है। आपकी समस्या का एक अधिक सामान्य समाधान शायद संदर्भ के बजाय अपनी वस्तु में केवल एक सूचक को संग्रहीत करना होगा। उदाहरण के लिए:

class T {
private:
    const U* _u;

public:
    T(const U& u)
        : _u(&u) {}
    …
};
1
Michael Kenzel 16 जिंदा 2019, 16:45

आपके इंटरफ़ेस के साथ एक प्रमुख समस्या यह है कि T का एकमात्र निर्माता एक const U& लेता है। इसका मतलब है कि आप एक अस्थायी को T पास कर सकते हैं और एक मृत वस्तु के लिए एक reference_wrapper के साथ छोड़ दिया जा सकता है क्योंकि किसी वस्तु में const& अस्थायी के जीवनकाल का विस्तार नहीं करता है।

इसे हल करने के लिए आपको एक हटाए गए कंस्ट्रक्टर को जोड़ना होगा जो आपको अस्थायी स्वीकार करने से रोकता है। जोड़ा जा रहा है

T(const U&&) = delete;

वह करेगा।

2
NathanOliver 16 जिंदा 2019, 16:35