C ++ 11 में auto_ptr पदावनति के लिए डिज़ाइन परिवर्तनों को कैसे संभालें?


12

हम C ++ 11 (यानी, -std=c++11) के तहत एक पुस्तकालय का परीक्षण कर रहे हैं । पुस्तकालय का उपयोग करता है auto_ptrऔर इस पैटर्न:

Foo* GetFoo()
{
    autoptr<Foo> ptr(new Foo);

    // Initialize Foo
    ptr->Initialize(...);

    // Now configure remaining attributes
    ptr->SomeSetting(...);

    return ptr.release();
}

C ++ 11 को हटा दिया गया है auto_ptr, इसलिए हम इससे दूर जाना चाहते हैं।

हालाँकि, कोड C ++ 03 और C ++ 11, दोनों को सपोर्ट करता है, इसलिए यह yanking के रूप में सरल नहीं है auto_ptr। यह भी उल्लेखनीय है कि पुस्तकालय की कोई बाहरी निर्भरता नहीं है। यह C ++ 03 का उपयोग करता है; और ऑटोटूलस, सीमेक, बूस्ट, का उपयोग नहीं करता है ...

auto_ptrC ++ 03 के साथ संगतता बनाए रखते हुए हमें C ++ 11 से दूर जाने के लिए डिज़ाइन परिवर्तनों को कैसे संभालना चाहिए ?


क्या कोई भी auto_ptrस्कोप्ड (यानी std::auto_ptr) है, क्या उन्हें कुछ अन्य नामस्थानों से स्मार्ट पॉइंटर प्राप्त करने की आवश्यकता है या हो सकती है?
नियाल

एक तरफ के रूप में, आप Foo::Initializeमें गुना करना चाह सकते हैं Foo::Foo
MSalters

1
@MSalters - हाँ, यह हमेशा उन चीजों में से एक रहा है जिनके बारे में मैंने हल्के से असहज महसूस किया है। पुस्तकालय 1990 के दशक में डिजाइन किया गया था, और मुझे लगता है कि डिजाइन MFC के समान था। अर्थात्, निम्न स्तर C ++ निर्माण था, और फिर एक "उच्च स्तर" ऑब्जेक्ट निर्माण। मुझे लगता है कि सुविधा का उपयोग ट्रेडऑफ़ के रूप में किया गया था ताकि वर्गों में 6 या 12 विभिन्न निर्माता न हों। (इस बिंदु पर, मैंने जो कुछ किया है वह सुनिश्चित किया गया है और सुनिश्चित किया गया है कि POD प्रकारों के सदस्य चर C ++ कंस्ट्रक्टर्स में साने चूक के लिए आरंभिक हैं)।

जवाबों:


13

ज्यादातर मामलों std::unique_ptrमें (लेकिन सुरक्षित) प्रतिस्थापन में ड्रॉप करने के लिए बनाया गया था std::auto_ptr, इसलिए बहुत कम (यदि कोई हो) कोड को छोड़कर अन्य आवश्यक परिवर्तन होना चाहिए (जैसा कि आप पूछते हैं) कोड को unique_ptrया तो उपयोग करने के लिए निर्देशित करना auto_ptr

ऐसा करने के कुछ तरीके (और प्रत्येक नीचे अपनी स्वयं की सूची के साथ आता है)। प्रदान किए गए कोड नमूने को देखते हुए, मैं पहले दो विकल्पों में से किसी एक का पक्ष लूंगा

विकल्प 1

#if __cplusplus >= 201103L
template <typename T>
using auto_ptr = std::unique_ptr<T>;
#else
using std::auto_ptr;
#endif

समझौतों से;

  • आप auto_ptrवैश्विक नामस्थान में नाम का परिचय देते हैं ; आप इसे परिभाषित करके इसे अपने स्वयं के "निजी" नामस्थान कह सकते हैं
  • एक बार C ++ 17 में माइग्रेट करने के बाद (मेरा मानना ​​है कि auto_ptrपूरी तरह से हटा दिया जाएगा) आप अधिक आसानी से खोज और बदल सकते हैं

विकल्प 2

template <typename T>
struct my_ptr {
    #if __cplusplus >= 201103L
    typedef std::unique_ptr<T> ptr;
    #else
    typedef std::auto_ptr<T> ptr;
    #endif
};

समझौतों से;

  • संभवतः अधिक बोझिल काम करने के लिए, सभी वर्तमान auto_ptrको कोड में बदलने की आवश्यकता है जैसे कुछmy_ptr<T>::ptr
  • बेहतर सुरक्षा के नाम वैश्विक नामस्थान में पेश नहीं किए जा रहे हैं

विकल्प 3

कुछ हद तक विवादास्पद, लेकिन अगर आप stdएक आधार के रूप में एक वर्ग होने के गुटों के साथ तैयार हैं

#if __cplusplus >= 201103L
template <typename T>
using my_ptr = std::unique_ptr<T>;
#else
template <typename T>
class my_ptr : public std::auto_ptr<T> {
  // implement the constructors for easier use
  // in particular
  explicit my_ptr( X* p = 0 ) : std::auto_ptr(p) {}
};
#endif

समझौतों से;

  • विरासत में मिले वर्ग का उपयोग करने की कोशिश न करें जहां एक आभासी आधार (विशेष रूप से गैर-आभासी विध्वंसक) की उम्मीद की जाएगी। ऐसा नहीं है कि यह मामले में एक मुद्दा होना चाहिए - लेकिन इसके बारे में पता होना चाहिए
  • फिर से, कोड बदल जाता है
  • संभावित नाम स्थान बेमेल है - यह सब इस बात पर निर्भर करता है कि पॉइंटर क्लास का उपयोग किस तरह से शुरू करने के लिए किया जाता है

विकल्प 4

एक नई कक्षा में पॉइंटर्स लपेटें और सदस्य को आवश्यक कार्य एकत्र करें

template <typename T>
class my_ptr { // could even use auto_ptr name?
  #if __cplusplus >= 201103L
  std::unique_ptr<T> ptr_;
  #else
  std::auto_ptr<T> ptr_;
  #endif

  // implement functions required...
  T* release() { return ptr_.release(); }
};

समझौतों से;

  • थोड़ा चरम जब आप वास्तव में चाहते हैं तो कार्यान्वयन को "स्वैप" करना है

बहुत अच्छा जवाब। मैंने वास्तव में इस पर थोड़ा शोध किया और आपने मेरे द्वारा किए गए परीक्षणों में से कम से कम तीन परीक्षण किए। (आपके पास जो कमी है वह है OS X और Clang विशिष्ट सामान। OS X एक भालू है क्योंकि यह अभी भी C1 03 के लिए TR1 नामस्थान का उपयोग करता है, और आपको इस पद्धति का उपयोग करके चीजों को शामिल करना होगा: नाम में ace unique_ptr ’नाम का कोई प्रकार नहीं एलएलवीएम / क्लैंग के तहत संकलन करते समय 'एसटीडी'

@jww। मैं OS X पर हूँ (XCode 6.4 और Apple LLVM संस्करण 6.1.0 (clang-602.0.53) (LLVM 3.6.0svn पर आधारित)) और C + ०३ / ११ के साथ कोई समस्या tr1नहीं है। वहाँ होने के नाते (मैं libc ++ का उपयोग करता हूं और libstdc ++ का नहीं)। मुझे पता है कि tr1 गैर-मानक था, लेकिन मैं ड्राफ्ट (यहां) में कहीं भी नहीं पाया जा सकता है कि फ़ाइलों को बिल्कुल होना चाहिए <tr1/...>, यह उल्लेख करता है कि हेडर <memory>आदि में बस tr1नामस्थान में फ़ाइल होने का उल्लेख है ।
निल

@jww। मुझे लगता है कि संकलक, पुस्तकालय और लक्ष्य डिवाइस के एक विशेष मिश्रण को देखते हुए - आपको कुछ और हाथ खड़े करने की आवश्यकता हो सकती है। ओएस एक्स पर एल्स, क्लैंग और लिबेक ++ में जाने पर विचार करें। सच कहूँ तो मैं libc ++ को OS के लिए नया "देशी" C ++ पुस्तकालय मानता हूं - मैं इसे डिफ़ॉल्ट रूप से लिखूंगा। मेरे पास इन दावों का समर्थन करने का कोई तरीका नहीं है कि क्लैंग / ऐप्पल रिलेशनशिप का इतिहास और कि ओएस एक्स पर जीसीसी टूल्स पुराने हैं (लाइब्रेरी) या अभी तक हटाए गए हैं (जहां तक ​​मुझे पता है कि जीसीसी वैसे भी एक पतली ठूंठ है) )।
निआल

"एक्स, ओएस एक्स पर, क्लैंग और लीबक ++ पर जाने पर विचार करें ..." - हाँ, मैं आपसे सहमत हूं। हालाँकि, हम उपयोगकर्ताओं को यह पसंद करने देना चाहते हैं, न कि उन पर बल देना चाहते हैं। (वे स्पष्ट रूप से चुनाव करते हैं जब वे निर्दिष्ट करते हैं (या अभाव) CXX=...)।

यहाँ मामला है जो मुझे OS X 10.7 और 10.8: पर इतना परेशान कर रहा है c++ -v -std=c++11 -x c++ - < /dev/null। मैं grep'dशामिल निर्देशिकाओं को डंप किया गया था, और वे शामिल नहीं हैं unique_ptr

0

विकल्प 5: प्रत्यक्ष उपनाम।

#if __cplusplus >= 201103L
template<typename T> 
using MyPtr = std::unique_ptr<T>;
#else 
#define MyPtr std::auto_ptr
#endif 

समझौतों से:

  1. नए भाषा संस्करणों के लिए, AKA C ++ 11 और बाद में, आपका उपनाम सही स्मार्ट पॉइंटर में मैप करता है। कोई भी उपयोगकर्ता कोड जो वास्तव में std के लिए विशिष्ट API पर निर्भर करता है :: auto_ptr संकलक द्वारा फ़्लैग किया जाएगा, जो कि अंतिम गारंटी है कि यह वास्तव में ठीक हो जाएगा।

  2. लीगेसी c ++ 03 मोड में उपनाम अन्य एक मैक्रो है। यह सकल है, लेकिन परिणामी वाक्यविन्यास MyPtr<T>बाकी कोड में C ++ 11 मामले के समान होगा।

  3. इसे स्थापित करने के लिए आपको अपने सभी ऑटो_प्रेट वैरिएबल खोजने और बदलने होंगे MyPtr


1
यह बहुत स्पष्ट नहीं है कि यह क्या संदर्भित है (और, जैसा कि वाक्यांशबद्ध है, यह बिल्कुल भी सवाल नहीं है)।
ऑटोफेज

1
@ अनाथालय मैं इसका उत्तर मानता हूं ... इसलिए शायद यह सवाल नहीं है।
Kain0_0
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.