2012-01-15 13 views
13

सी ++ 03 आपको const, volatile, और/या lvalue संदर्भ (&) के रूप में फ़ंक्शन पैरामीटर योग्यता देता है।सी ++ 11: कॉन्स, अस्थिर, lvalue संदर्भ, और rvalue संदर्भ योग्य सदस्य समारोह पॉइंटर्स पर सार?

सी ++ 11 एक और जोड़ता है: रावल संदर्भ (&&)।

इसके अलावा, सी ++ आपको अपने पैरामीटर के क्वालीफायर के आधार पर फ़ंक्शन ओवरलोड करने देता है, ताकि फ़ंक्शन को कॉल करते समय सबसे उचित ओवरलोड का चयन किया जा सके।

एक सदस्य फ़ंक्शन अवधारणात्मक रूप से एक फ़ंक्शन के रूप में सोचा जा सकता है जो एक अतिरिक्त पैरामीटर लेता है, जिसका प्रकार उस वर्ग के उदाहरण का संदर्भ है जिसमें यह सदस्य है। किसी अन्य पैरामीटर के समान ही इस 'अतिरिक्त पैरामीटर' के क्वालीफायर के आधार पर सदस्य फ़ंक्शन को अधिभार करना संभव है। इस समारोह हस्ताक्षर के अंत में क्वालिफायर डालकर व्यक्त किया जाता है:

struct Foo 
{ 
    int& data();    // return a non-const reference if `this` is non-const 
    const int& data() const; // return a const reference if `this` is const 
}; 

में सी ++ 03, const और volatile क्वालिफायर संभव हो रहे हैं, और सी ++ 11 भी अनुमति देता है & और && (& सैद्धांतिक रूप से हो सकता था सी ++ 03 में अनुमति दी गई थी, लेकिन यह नहीं थी)।

क्वालिफायर का कोई भी संयोजन अपवाद है कि & और && परस्पर अनन्य हैं, जो 2^2 = 4 सी ++ 03 में संभावनाओं और सी ++ 11 में 2^4-4 = 12 के लिए बनाता है के साथ इस्तेमाल किया जा सकता । जब आप सदस्य समारोह संकेत के साथ काम करना चाहते हैं

यह काफी दर्द हो सकता है, क्योंकि वे भी एक छोटा सा इन क्वालिफायर में बहुरूपी नहीं हैं: एक सदस्य समारोह सूचक की "this प्रकार" एक के रूप में पारित पर क्वालिफायर तर्क उन पैरामीटर के प्रकार पर बिल्कुल मेल खाना चाहिए जो इसे पारित किया जा रहा है। सी ++ क्वालिफायर पर अमूर्त के लिए कोई स्पष्ट सुविधा भी प्रदान नहीं करता है। सी ++ 03 में यह अधिकतर ठीक था, क्योंकि आपको const संस्करण और गैर-const संस्करण लिखना होगा और कोई भी volatile परवाह नहीं करेगा, लेकिन सी ++ 11 में पैथोलॉजिकल केस में (जो कि असामान्य नहीं है रोगजनक है) आपको मैन्युअल रूप से 12 ओवरलोड लिखना पड़ सकता है। प्रति कार्य

मैं खोजने के लिए बहुत खुश था कि आप एक टेम्पलेट पैरामीटर के रूप में संलग्नित क्लास के प्रकार से गुजर रहे हैं, तो और इसे से एक सदस्य समारोह सूचक के प्रकार निकाले जाते हैं, कि const और volatile क्वालिफायर की अनुमति दी और प्रचारित कर रहे हैं के रूप में आप उम्मीद करेंगे :

template<typename Object> 
struct Bar 
{ 
    typedef int (Object::*Sig)(int); 
}; 

Bar<Baz>;    // Sig will be `int (Baz::*)(int)` 
Bar<const Baz>;   // Sig will be `int (Baz::*)(int) const` 
Bar<volatile Baz>;  // Sig will be `int (Baz::*)(int) volatile` 
Bar<const volatile Baz>; // Sig will be `int (Baz::*)(int) const volatile` 

यह एक बड़ा सौदा मैन्युअल सभी मामलों को लिखने के लिए की तुलना में अच्छे है।

दुर्भाग्य से, यह & और && के लिए काम नहीं करता प्रतीत होता है।

जीसीसी 4.7 का कहना है:

error: forming pointer to reference type ‘Baz&&’

लेकिन वह है कि जीसीसी 4.7 के रूप में अभी तक this पर संदर्भ क्वालिफायर के लिए समर्थन नहीं है को देखते हुए भी आश्चर्य की बात नहीं है,।

error: member pointer refers into non-class type 'Baz &&'

ओह, अच्छी तरह से:

मैं भी बजना 3.0 है, जो इस तरह के समर्थन करता है के साथ की कोशिश की।

क्या मैं यह निष्कर्ष निकालने में सही हूं कि यह संभव नहीं है, और सदस्य फ़ंक्शन पॉइंटर्स के "this type" पर संदर्भ क्वालीफायरों पर अमूर्त करने का कोई तरीका नहीं है? जब आप टेम्पलेट पैरामीटर के रूप में "this प्रकार" पास कर रहे हों तो विशिष्ट मामले के अलावा क्वालीफायर (विशेष रूप से this पर) के लिए कोई अन्य तकनीक भी सराहना की जाएगी।

(यह इंगित करने योग्य है कि यदि सी ++ सदस्य कार्यों और सामान्य कार्यों के बीच अंतर नहीं करता है, तो यह सब छोटा होगा: आप टेम्पलेट पैरामीटर का उपयोग फ़ंक्शन (पॉइंटर) के पैरामीटर के प्रकार के रूप में करेंगे, और टेम्पलेट तर्क के रूप में पारित किया जाएगा, क्वालीफायर बरकरार, कोई अतिरिक्त विचार जरूरी नहीं है।)

+1

क्वालिफायर के सभी संभावित संयोजनों के लिए आपको कितनी बार विभिन्न व्यवहार की आवश्यकता है? (या, उस मामले के लिए, यहां तक ​​कि दो या तीन संभावित संयोजन?) –

+1

यदि मैं फ़ंक्शन-जैसी ऑब्जेक्ट्स के लिए एक अमूर्त लिखने की कोशिश कर रहा हूं (std :: function की भावना में लेकिन समान नहीं) तो पूर्णता एक लक्ष्य लक्ष्य है । मैं वास्तव में extrapolate या अनुमान नहीं कर सकता (कितनी बार के रूप में) लेकिन मुझे पता है कि मैं इससे पहले भाग गया है। – glaebhoerl

उत्तर

4

क्या आपने बस अपने टेम्पलेट को विशेषज्ञता देने के बारे में सोचा है?

तुम सिर्फ दो संस्करणों में जोड़ सकते हैं:

template <typename Object> 
struct Bar<Object&> { 
    typedef int (Object::*Sig)(int)&; 
}; 

template <typename Object> 
struct Bar<Object&&> { 
    typedef int (Object::*Sig)(int)&&; 
}; 

और फिर संकलक उचित रूप से सही विशेषज्ञता ले जाएगा (या सामान्य स्थिति पर वापस आने)।

यह आपको const/volatile चीज़ से बचाता है, लेकिन इसका मतलब यह है कि आपको कोड को 3 बार लिखना होगा।

+0

हाँ, तथ्य यह है कि 'कॉन्स्ट' और 'अस्थिर' को बुद्धिमानी से संभाला जाता है, इसका मतलब है कि मुझे केवल बारह के बजाय तीन संस्करण लिखना है, जो अच्छा है। – glaebhoerl

संबंधित मुद्दे