कक्षा के लिए कुछ शर्तों में सी ++ कंपाइलर निहित डिफ़ॉल्ट कन्स्ट्रक्टर, कॉपी कन्स्ट्रक्टर, विनाशक, रूपांतरण ऑपरेटर, असाइनमेंट ऑपरेटर इत्यादि और अन्य निहित विधियों को जोड़ता है।

मैं कम से कम संभव तरीके से सभी संभावित निहित तरीकों को कैसे अक्षम/हटा सकता हूं?

मैं नहीं चाहता कि मेरी कक्षा गैर-प्रतिलिपि योग्य हो, मैं केवल इन डिफ़ॉल्ट विधियों को अक्षम करना चाहता हूं ताकि संकलक संकलन त्रुटि फेंक दे और मैं उन्हें स्वयं लागू कर सकूं। मैं सिर्फ अति-नियंत्रण रखना चाहता हूं, ताकि संकलक मेरी कक्षा के बारे में कोई मूक कार्य न करे।

उदाहरण के लिए मैं अगली बात कर सकता हूं (यह सिर्फ एक डमी उदाहरण है, वास्तविक जीवन में मेरे पास कोई जटिल वर्ग हो सकता है):

class C {
private:
    C() = delete;
    C(C const & other) = delete;
    C & operator = (C const & other) = delete;
};

लेकिन यह लंबा रास्ता है, मैं कुछ तरीकों के हस्ताक्षर को हटाना भी भूल सकता हूं और मुझे उन सभी को हटाने की जरूरत है। ताकि मैं खरोंच से सभी तरीकों को अपने आप से फिर से लागू करूं।

और मुझे उन सभी विधियों के लिए त्रुटियों को देखने की ज़रूरत है जो अन्य कोड की आवश्यकता/उपयोग करते हैं और जिन्हें मैंने अभी तक लागू नहीं किया है, इसके बजाय संकलक चुपचाप मेरे लिए उन तरीकों को लागू कर रहा है।

इसके अलावा अगर मैं अपने उदाहरण में ऊपर दी गई डिफ़ॉल्ट विधियों को हटा देता हूं, तो मैं कैसे सुनिश्चित कर सकता हूं कि कोई अन्य चुपचाप बनाई गई विधियां नहीं हैं? क्या कंपाइलर द्वारा चुपचाप बनाए गए 100% सभी मानक विधियों की सूची ऑनलाइन है?

2
Arty 9 फरवरी 2021, 14:30

3 जवाब

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

आप एक मिश्रित दृष्टिकोण के लिए जा सकते हैं। एक बार बोझिल वर्ग को परिभाषित करें

class DeleteAllSpecialMemebers {
private:
    DeleteAllSpecialMemebers() = delete;
    DeleteAllSpecialMemebers(DeleteAllSpecialMemebers const &) = delete;
    DeleteAllSpecialMemebers & operator = (DeleteAllSpecialMemebers const &) = delete;
    DeleteAllSpecialMemebers(DeleteAllSpecialMemebers &&) = delete;
    DeleteAllSpecialMemebers & operator = (DeleteAllSpecialMemebers &&) = delete;
protected:
    struct token { explicit token() = default; };
    DeleteAllSpecialMemebers(token) {}
};

फिर इससे विरासत में मिलता है:

class C : private DeleteAllSpecialMemebers{
public:
    C(int) : DeleteAllSpecialMemebers(token{}) {}
};

अतिरिक्त token प्रकार व्युत्पन्न कक्षाओं को अन्य कंस्ट्रक्टरों को लागू करने की अनुमति देना है, जैसे C::C(int) (या यहां तक ​​कि उपयोगकर्ता द्वारा प्रदत्त C::C())।

इसे लाइव देखें

5
Arty 9 फरवरी 2021, 15:19

पुन: प्रयोज्य डमी बेस क्लास का सबसे छोटा विकल्प हो सकता है:

struct NoSpecialMember {
    NoSpecialMember(const NoSpecialMember&) = delete;
    NoSpecialMember& operator=(const NoSpecialMember&) = delete;
    NoSpecialMember(NoSpecialMember&&) = delete;
    NoSpecialMember& operator=(NoSpecialMember&&) = delete;
    ~NoSpecialMember() = default;
};

यह privateगीत प्राप्त करने के लिए पर्याप्त है;

class Test : private NoSpecialMember {};

निम्नलिखित परिणाम के साथ:

static_assert(!std::is_copy_constructible_v<Test>);
static_assert(!std::is_copy_assignable_v<Test>);
static_assert(!std::is_move_constructible_v<Test>);
static_assert(!std::is_move_assignable_v<Test>);
1
lubgr 9 फरवरी 2021, 14:42

सहायक को परिभाषित करें और इसे उस वर्ग के क्षेत्र के रूप में उपयोग करें जहां इसे अक्षम किया जाना चाहिए:

struct DisableCopyAssign
{
    DisableCopyAssign(char){}
    DisableCopyAssign(const DisableCopyAssign&) = delete;
    DisableCopyAssign(DisableCopyAssign&&) = delete;
};

class Foo
{
private:
    DisableCopyAssign dummy;
};

https://gcc.godbolt.org/z/ce8sjq

1
Marek R 9 फरवरी 2021, 14:58