C ++ 11 के साथ आगे संगतता प्राप्त करना


12

मैं एक बड़े सॉफ़्टवेयर एप्लिकेशन पर काम करता हूं जो कई प्लेटफार्मों पर चलना चाहिए। इनमें से कुछ प्लेटफ़ॉर्म C ++ 11 (जैसे MSVS 2010) की कुछ विशेषताओं का समर्थन करते हैं और कुछ किसी का समर्थन नहीं करते हैं (उदाहरण GCC 4.3.x)। मैं इस स्थिति को कई वर्षों तक जारी रखने की उम्मीद करता हूं (मेरा सबसे अच्छा अनुमान: 3-5 साल)।

यह देखते हुए, मैं एक अनुकूलता इंटरफ़ेस स्थापित करना चाहूंगा जैसे (जो भी संभव हो) लोग C ++ 11 कोड लिख सकते हैं जो अभी भी पुराने संकलक के साथ न्यूनतम रखरखाव के साथ संकलित करेंगे। कुल मिलाकर, लक्ष्य है कि # ifdef का यथासंभव कम से कम उपयोग करना जबकि अभी भी उन प्लेटफॉर्म पर बेसिक C ++ 11 सिंटैक्स / फीचर्स को सक्षम करना और उन्हें समर्थन न करने वाले प्लेटफॉर्म पर इम्यूलेशन प्रदान करना है।

चलिए std :: move () से शुरू करते हैं। अनुकूलता प्राप्त करने का सबसे स्पष्ट तरीका कुछ इस तरह से एक आम हेडर फ़ाइल में होगा:

#if !defined(HAS_STD_MOVE)
namespace std { // C++11 emulation
  template <typename T> inline T& move(T& v) { return v; }
  template <typename T> inline const T& move(const T& v) { return v; }
}
#endif // !defined(HAS_STD_MOVE)

यह लोगों को चीजों को लिखने की अनुमति देता है

std::vector<Thing> x = std::move(y);

... नपुंसकता के साथ। यह वही करता है जो वे C ++ 11 में चाहते हैं और यह C ++ 03 में सबसे अच्छा काम करता है। जब हम अंत में C ++ 03 संकलक के अंतिम को छोड़ देते हैं, तो यह कोड इस प्रकार रह सकता है।

हालांकि, मानक के अनुसार, नए प्रतीकों को stdनाम स्थान में इंजेक्ट करना अवैध है । यही सिद्धांत है। मेरा प्रश्न है: व्यावहारिक रूप से बोलना क्या आगे की अनुकूलता प्राप्त करने के तरीके के रूप में ऐसा करने में कोई नुकसान है?


1
बूस्ट इसमें पहले से ही काफी कुछ प्रदान करता है, और पहले से ही जब / जहां उपलब्ध हो नई सुविधाओं का उपयोग करने के लिए कोड है, इसलिए आप बस बूस्ट प्रदान करता है और इसके साथ किया जा सकता है। बेशक, सीमाएं हैं - अधिकांश नई सुविधाओं को विशेष रूप से जोड़ा गया था क्योंकि पुस्तकालय-आधारित समाधान पर्याप्त नहीं हैं।
जेरी कॉफिन

हां, मैं विशेष रूप से उन विशेषताओं के बारे में सोच रहा हूं जिन्हें लाइब्रेरी स्तर पर लागू किया जा सकता है, न कि वाक्य-रचना संबंधी परिवर्तनों के बारे में। बूस्ट वास्तव में (निर्बाध) आगे की संगतता के मुद्दे को संबोधित नहीं करता है। जब तक मैं कुछ याद कर रहा हूँ ...
mcmcc

Gcc 4.3 में पहले से ही C ++ 11 की एक अच्छी सुविधा है, Rvalue-reference शायद सबसे महत्वपूर्ण है।
Jan Hudec

@ जानहुडेक: आप सही कह रहे हैं। गरीब का उदाहरण। किसी भी स्थिति में, अन्य कंपाइलर हैं जो निश्चित रूप से सिंटैक्स का समर्थन नहीं करते हैं (जैसे आईबीएम के C ++ कंपाइलर का जो भी संस्करण है)।
mcmcc

जवाबों:


9

मैं अपने C ++ प्रोग्राम्स में फॉरवर्ड- और बैकवर्ड-कम्पैटिबिलिटी के स्तर को बनाए रखते हुए एक अच्छे के लिए काम कर रहा हूं, जब तक कि मुझे अंततः इसके लिए लाइब्रेरी टूलकिट नहीं बनाना पड़ता , जिसे मैं रिलीज़ करने की तैयारी कर रहा हूं । सामान्य तौर पर, जब तक आप स्वीकार करते हैं कि आपको "पूर्ण" फॉरवर्ड-संगतता नहीं मिलेगी, न ही फीचर्स में (कुछ चीजों को केवल आगे-अनुकरण नहीं किया जा सकता है) सिंटैक्स में नहीं (आपको संभवतः मैक्रोज़, वैकल्पिक नामस्थान का उपयोग करना होगा कुछ चीजें) तो आप सब तैयार हैं।

वहाँ सुविधाओं का एक अच्छा है कि C ++ 03 में एक स्तर है कि व्यावहारिक उपयोग के लिए पर्याप्त है में अनुकरण किया जा सकता है - और बिना किसी परेशानी के जो कि उदाहरण के लिए आता है: बूस्ट। हेक, यहां तक ​​कि C ++ मानकों का प्रस्ताव nullptrC ++ 03 बैकपोर्ट के लिए सुझाव देता है। और फिर सब कुछ के लिए उदाहरण के लिए TR1 है C ++ 11 ‑ लेकिन ‑ हमारे पास ‑ ‑ वर्षों के सामान के लिए ‑ पूर्वावलोकन हैं। इतना ही नहीं, कुछ C ++ 14 में मुखर वेरिएंट, पारदर्शी फंक्शनलर्स जैसे फीचर्स और C ++ 03 में लागू किए जा optional सकते हैं!

केवल दो चीजें जो मुझे पता है कि बिल्कुल बैकपार्ट नहीं की जा सकती हैं वे हैं कॉन्स्टैक्स और वेरैडिक टेम्पलेट।

नेमस्पेस में सामान जोड़ने के पूरे मामले के संबंध में std, मेरा विचार यह है कि इससे कोई फर्क नहीं पड़ता - बिल्कुल भी नहीं । बूस्ट के बारे में सोचो, सबसे महत्वपूर्ण और प्रासंगिक C ++ पुस्तकालयों में से एक, और TR1 का उनका कार्यान्वयन: Boost.Tr1। यदि आप C ++ में सुधार करना चाहते हैं, तो इसे C ++ 11 के साथ संगत करें, तो परिभाषा के अनुसार आप इसे ऐसी चीज़ में बदल रहे हैं जो C ++ 03 नहीं है, इसलिए अपने आप को एक मानक से अधिक अवरुद्ध करें जिसे आप किसी भी तरह से बचने या छोड़ने का इरादा रखते हैं। , सीधे शब्दों में कहें तो उल्टा। शुद्धतावादी शिकायत करेंगे, लेकिन परिभाषा के अनुसार किसी को उनकी परवाह नहीं करनी चाहिए।

बेशक, सिर्फ इसलिए कि आप (03) मानक का पालन नहीं करेंगे, इसका मतलब यह नहीं है कि आप कोशिश नहीं कर सकते हैं, या उल्लासपूर्वक इसे तोड़ने के लिए नहीं जाएंगे। ये मुद्दा नहीं है। इसलिए जब तक आप stdनेमस्पेस में जोड़ा जाता है तब तक बहुत सावधानी से नियंत्रण रखें , और उन वातावरण का नियंत्रण रखें जहां आपके सॉफ़्टवेयर का उपयोग किया जाता है (यानी: परीक्षण करते हैं!), किसी भी तरह का कोई भी अहितकर नुकसान नहीं होना चाहिए। यदि संभव हो तो, एक अलग नामस्थान में सब कुछ परिभाषित करें और केवल नामस्थान में usingनिर्देश जोड़ें stdताकि आप वहां कुछ भी नहीं जोड़ रहे हैं जो "बिल्कुल" अंदर जाने की आवश्यकता है। कौन सा, IINM, कम या ज्यादा Boost.TR1 करता है।


अद्यतन (२०१३) : मूल प्रश्न के अनुरोध के रूप में और कुछ टिप्पणियों को देखते हुए जिन्हें मैं निरसन की कमी के कारण नहीं जोड़ सकता, यहां C ++ 11 और C ++ 14 विशेषताओं की सूची है और उनकी पोर्टेबिलिटी की डिग्री है से सी ++ 03:

  • nullptr: आधिकारिक समिति के बैकपोर्ट को पूरी तरह से लागू करने योग्य; आपको संभवतः कुछ टाइप_ट्रेट्स विशेषज्ञता प्रदान करनी होगी ताकि इसे "मूल" प्रकार के रूप में पहचाना जा सके।
  • forward_list: पूरी तरह से लागू करने योग्य, हालांकि आवंटनकर्ता का समर्थन इस पर निर्भर करता है कि आपका ट्र 1 इम्प्लांटेंटेशन क्या प्रदान कर सकता है।
  • नए एल्गोरिदम (विभाजन_कोपी, आदि): पूरी तरह से लागू करने योग्य।
  • ब्रेस-सीक्वेंस (उदाहरण :) से कंटेनर कंस्ट्रक्शन vector<int> v = {1, 2, 3, 4};: पूरी तरह से लागू करने योग्य, हालांकि एक से अधिक वर्डियर चाहेंगे।
  • static_assert: मैक्रो के रूप में लागू होने पर लगभग पूरी तरह से लागू करने योग्य (आपको केवल अल्पविराम से सावधान रहना होगा)।
  • unique_ptr: लगभग पूरी तरह से लागू करने योग्य, लेकिन आपको कॉलिंग कोड (कंटेनर में उन्हें संग्रहीत करने के लिए आदि) से भी समर्थन की आवश्यकता होगी; हालांकि नीचे देखें।
  • rvalue-reference: आप उनसे कितना प्राप्त करने की उम्मीद करते हैं (उदाहरण: बूस्ट मूव) के आधार पर लगभग पूरी तरह से लागू करने योग्य।
  • Foreach iteration: पूरी तरह से लागू करने योग्य, वाक्यविन्यास कुछ अलग होगा।
  • तर्कों के रूप में स्थानीय कार्यों का उपयोग करना (उदाहरण के लिए: ट्रांसफ़ॉर्म करना): निकट-पूरी तरह से लागू करने योग्य, लेकिन वाक्यविन्यास पर्याप्त रूप से भिन्न होगा - उदाहरण के लिए, स्थानीय फ़ंक्शन कॉल साइट पर परिभाषित नहीं हैं, लेकिन ठीक पहले।
  • स्पष्ट रूपांतरण ऑपरेटर: व्यावहारिक स्तर पर लागू (रूपांतरण को स्पष्ट किया जा रहा है), इम्परफेक्ट C ++ का "स्पष्ट_कास्ट" देखें; लेकिन भाषा की विशेषताओं के साथ एकीकरण static_cast<>निकट-असंभव हो सकता है।
  • तर्क अग्रेषण: व्यावहारिक स्तर पर लागू किया गया है जो ऊपर दिए गए संदर्भ-संदर्भों पर दिया गया है, लेकिन आपको अपने तर्कों को आगे बढ़ाने के लिए एन ओवरलोड प्रदान करना होगा।
  • चाल: व्यावहारिक स्तर पर लागू करने योग्य (दो एब्स देखें)। बेशक, आपको इससे लाभ के लिए संशोधक कंटेनरों और वस्तुओं का उपयोग करना होगा।
  • बंद आवंटनकर्ता: वास्तव में लागू करने योग्य नहीं है जब तक कि आपका Tr1 कार्यान्वयन इसकी सहायता नहीं कर सकता है।
  • मल्टीबाइट चरित्र प्रकार: वास्तव में लागू नहीं जब तक कि आपका ट्र 1 आपको समर्थन नहीं दे सकता। लेकिन अभीष्ट उद्देश्य के लिए विशेष रूप से मामले से निपटने के लिए डिज़ाइन की गई लाइब्रेरी पर भरोसा करना बेहतर है, जैसे कि ICU, भले ही C ++ 11 का उपयोग कर रहे हों।
  • वैरिएड तर्क सूची: कुछ परेशानी के साथ लागू करने योग्य, तर्क अग्रेषण पर ध्यान दें।
  • noexcept: आपके कंपाइलर की विशेषताओं पर निर्भर करता है।
  • नया autoशब्दार्थ और decltype: आपके संकलक की विशेषताओं पर निर्भर करता है - उदा __typeof__. : ।
  • आकार पूर्णांक प्रकार ( int16_t, आदि): आपके संकलक की विशेषताओं पर निर्भर करता है - या आप पोर्टेबल stdint.h पर प्रतिनिधि कर सकते हैं।
  • प्रकार विशेषताएँ: आपके संकलक की विशेषताओं पर निर्भर करती है।
  • प्रारंभिक सूची: मेरे ज्ञान के लिए लागू नहीं; लेकिन अगर आप जो चाहते हैं वह अनुक्रमों के साथ कंटेनरों को शुरू करना है, तो "कंटेनर निर्माण" पर उपरोक्त देखें।
  • टेम्प्लेट एलियासिंग: मेरे ज्ञान के लिए लागू करने योग्य नहीं है, लेकिन यह वैसे भी एक अनावश्यक विशेषता है, और हमने ::typeहमेशा के लिए टेम्पलेट्स में
  • Variadic टेम्पलेट्स: मेरे ज्ञान के लिए लागू नहीं; करीब टेम्पलेट तर्क डिफ़ॉल्ट है, जिसके लिए एन विशेषज्ञता की आवश्यकता होती है, आदि।
  • constexpr: मेरे ज्ञान के लिए लागू नहीं।
  • यूनिफ़ॉर्म इनिशियलाइज़ेशन: मेरे ज्ञान के लिए लागू नहीं है, लेकिन गारंटीकृत डिफ़ॉल्ट -कॉन्स्ट्रक्टर आरंभीकरण को एला बूस्ट के मूल्य-इनिशियलाइज़ किए जा सकते हैं।
  • सी ++ 14 dynarray: पूरी तरह से लागू करने योग्य।
  • C ++ 14 optional<>: जब तक आपका C ++ 03 कंपाइलर संरेखण सेटअप का समर्थन करता है, तब तक पूरी तरह से लागू होने योग्य है।
  • C ++ 14 पारदर्शी फ़ंक्शनलर्स: लगभग पूरी तरह से लागू करने योग्य, लेकिन आपके क्लाइंट कोड को स्पष्ट रूप से उदाहरण के std::less<void>लिए उपयोग करना होगा।
  • C ++ 14 नए मुखर वेरिएंट (जैसे assure): पूरी तरह से लागू करने योग्य यदि आप दावा करते हैं, तो लगभग पूरी तरह से लागू करने योग्य है यदि आप इसके बजाय थ्रो को सक्षम करना चाहते हैं।
  • C ++ 14 टूपल एक्सटेंशन (टाइप करके टपल एलीमेंट प्राप्त करें): पूरी तरह से लागू करने योग्य, और आप इसे फीचर प्रस्ताव में वर्णित सटीक मामलों के संकलन में विफल होने के लिए भी प्राप्त कर सकते हैं।

(अस्वीकरण: इन सुविधाओं में से कई मेरे सी ++ बैकग्राउंड लाइब्रेरी में कार्यान्वित की जाती हैं जिन्हें मैंने ऊपर लिंक किया है, इसलिए मुझे लगता है कि मुझे पता है कि मैं किस बारे में बात कर रहा हूं जब मैं "पूरी तरह से" या "निकट-पूर्ण" कहता हूं। "


6

यह मौलिक रूप से असंभव है। विचार करें std::unique_ptr<Thing>। यदि पुस्तकालय के रूप में प्रतिद्वंद्वियों के संदर्भों का अनुकरण करना संभव था, तो यह भाषा की विशेषता नहीं होगी।


1
मैंने कहा "जो भी संभव डिग्री के लिए"। स्पष्ट रूप से कुछ सुविधाओं को # ifdef के पीछे छोड़ दिया जाएगा या इसका बिल्कुल उपयोग नहीं किया जाएगा। std :: Move () ऐसा होता है कि आप सिंटैक्स का समर्थन कर सकते हैं (यद्यपि कार्यक्षमता नहीं है)।
mcmcc

2
वास्तव में प्रतिद्वंद्विता के संदर्भ प्रस्ताव में पुस्तकालय आधारित समाधान का उल्लेख है!
Jan Hudec

अधिक विशेष रूप से, सी ++ 03 में विशेष वर्ग के लिए चाल शब्दार्थों को लागू करना संभव है, इसलिए std::unique_ptrवहां परिभाषित करना संभव होना चाहिए , लेकिन यह कुछ अन्य विशेषताओं के संदर्भ हैं जिन्हें C ++ 03 में लागू नहीं किया जा सकता है, इसलिए std::forwardयह संभव नहीं है। दूसरी बात यह है कि यह std::unique_ptrउपयोगी नहीं होगा, क्योंकि संग्रह जब तक आप उन सभी को प्रतिस्थापित नहीं करते, तब तक शब्दार्थ का उपयोग नहीं करेंगे।
Jan Hudec

@ जानहुडेक: इसे परिभाषित करना संभव नहीं है unique_ptr। की विफलताओं को देखो auto_ptrunique_ptrव्यावहारिक रूप से एक वर्ग का पाठ्यपुस्तक उदाहरण है, जिसका शब्दार्थ भाषा की विशेषता द्वारा मौलिक रूप से सक्षम था।

@ डीडीएमजी: नहीं, ऐसा नहीं है unique_ptrकि यह मूलभूत रूप से भाषा की विशेषता है। हालांकि यह उस सुविधा के बिना बहुत उपयोगी नहीं होगा। क्योंकि सही अग्रेषण के बिना यह कई मामलों में उपयोग करने योग्य नहीं होगा और सही अग्रेषण से उस सुविधा की आवश्यकता नहीं होती है।
जन हडेक

2
  1. Gcc ने 4.3 में C ++ 11 (अभी भी C ++ 0x) की शुरुआत की। यह तालिका कहती है कि इसमें पहले से ही संदर्भ और कुछ अन्य कम इस्तेमाल की जाने वाली विशेषताएं हैं (आपको -std=c++0xउन्हें सक्षम करने के लिए विकल्प निर्दिष्ट करना होगा)।
  2. C ++ 11 में मानक पुस्तकालय के लिए कई परिवर्धन पहले से ही TR1 में परिभाषित किए गए थे और GNU stdlibc ++ उन्हें std :: tr1 नामस्थान में प्रदान करता है। तो बस उचित सशर्त का उपयोग कर।
  3. बूस्ट TR1 कार्यों में से अधिकांश को परिभाषित करता है और यदि आपके पास यह नहीं है, तो आप TR1 नेमस्पेस में इंजेक्ट कर सकते हैं (लेकिन VS2010 करता है और gcc 4.3 के साथ-साथ यदि आप GNU stdlibc ++ का उपयोग करते हैं)।
  4. stdनाम स्थान में कुछ भी डालना एक "अपरिभाषित व्यवहार" है। इसका मतलब है कि विनिर्देश यह नहीं कहता है कि क्या होगा। लेकिन अगर आप जानते हैं कि किसी विशेष मंच पर मानक पुस्तकालय कुछ परिभाषित नहीं करता है, तो बस आगे बढ़ें और इसे परिभाषित करें। बस उम्मीद करें कि आपको प्रत्येक प्लेटफ़ॉर्म पर जांचना होगा कि आपको क्या चाहिए और आप क्या परिभाषित कर सकते हैं।
  5. Rvalue संदर्भ के लिए प्रस्ताव, N1690 कैसे C ++ 03 कदम अर्थ विज्ञान को लागू करने का उल्लेख है। इसका इस्तेमाल विकल्प के रूप में किया जा सकता है unique_ptr। हालाँकि, यह बहुत उपयोगी नहीं होगा, क्योंकि यह वास्तव में चाल शब्दार्थों का उपयोग करके संग्रह पर निर्भर करता है और C ++ 03 स्पष्ट रूप से नहीं होगा।

1
आप जीसीसी के बारे में सही हैं, लेकिन दुर्भाग्य से, मुझे अन्य (गैर-जीसीसी) संकलकों का भी समर्थन करना होगा। आपके # 4 गोली सवाल मैं पूछ रहा हूँ के दिल में है। # 5 दिलचस्प है, लेकिन मैं इन पुराने प्लेटफार्मों पर कदम शब्दार्थ (प्रतिलिपि अनुकूलन) का समर्थन नहीं कर रहा हूं, बल्कि एक अनिवार्य वाक्यविन्यास के रूप में "std :: move ()"।
mcmcc 15
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.