2012-06-13 6 views
260

सी ++ 11 inline namespace एस की अनुमति देता है, जिनमें से सभी सदस्य स्वचालित रूप से संलग्न namespace में हैं। मैं इस के किसी भी उपयोगी अनुप्रयोग के बारे में नहीं सोच सकता - क्या कोई ऐसी स्थिति का एक संक्षिप्त, संक्षेप उदाहरण दे सकता है जहां inline namespace की आवश्यकता है और यह सबसे बेवकूफ समाधान कहां है? (इस परेशानी के लिए भीख माँग इसके अलावा, यह नहीं मेरे लिए स्पष्ट है जब एक namespace एक में inline लेकिन सभी घोषणाओं घोषित किया जाता है कि क्या होता है, जो विभिन्न फाइलों में रह सकता है। है ना?)इनलाइन नेमस्पेस के लिए क्या हैं?

उत्तर

259

इनलाइन नेमस्पेस symbol versioning की तरह एक लाइब्रेरी संस्करण सुविधा है, लेकिन एक विशिष्ट बाइनरी निष्पादन योग्य प्रारूप (यानी मंच-विशिष्ट) की सुविधा होने के बजाय पूरी तरह से सी ++ 11 स्तर (यानी क्रॉस-प्लेटफॉर्म) पर लागू किया गया है। ।

यह एक तंत्र है जिसके द्वारा एक लाइब्रेरी लेखक नेस्टेड नेमस्पेस लुक और कार्य कर सकता है जैसे कि इसकी सभी घोषणाएं आस-पास के नामस्थान में थीं (इनलाइन नेमस्पेस को नेस्टेड किया जा सकता है, इसलिए "अधिक घोंसला वाले" नाम सभी तरह से घूमते हैं पहले गैर-इनलाइन नामस्थान के लिए और देखो और कार्य करें जैसे कि उनकी घोषणाएं किसी भी नामस्थान में भी थीं)।

उदाहरण के तौर पर, vector के एसटीएल कार्यान्वयन पर विचार करें। अगर हम सी ++ 98 हैडर <vector> में सी ++ की शुरुआत है, तो से इनलाइन नामस्थान था इस तरह दिख रही हो सकता है:

namespace std { 

#if __cplusplus < 1997L // pre-standard C++ 
    inline 
#endif 

    namespace pre_cxx_1997 { 
     template <class T> __vector_impl; // implementation class 
     template <class T> // e.g. w/o allocator argument 
     class vector : __vector_impl<T> { // private inheritance 
      // ... 
     }; 
    } 
#if __cplusplus >= 1997L // C++98/03 or later 
         // (ifdef'ed out b/c it probably uses new language 
         // features that a pre-C++98 compiler would choke on) 
# if __cplusplus == 1997L // C++98/03 
    inline 
# endif 

    namespace cxx_1997 { 

     // std::vector now has an allocator argument 
     template <class T, class Alloc=std::allocator<T> > 
     class vector : pre_cxx_1997::__vector_impl<T> { // the old impl is still good 
      // ... 
     }; 

     // and vector<bool> is special: 
     template <class Alloc=std::allocator<bool> > 
     class vector<bool> { 
      // ... 
     }; 

    }; 

#endif // C++98/03 or later 

} // namespace std 

__cplusplus के मूल्य पर निर्भर करता है, या तो एक या अन्य vector कार्यान्वयन चुना जाता है। यदि आपका कोडबेस पूर्व-सी ++ 98 बार में लिखा गया था, और आप पाते हैं कि vector का C++ 98 संस्करण आपके कंपाइलर को अपग्रेड करते समय आपके लिए परेशानी पैदा कर रहा है, तो आपको "सभी" को संदर्भों को ढूंढना है std::vector अपने कोडबेस में और उन्हें std::pre_cxx_1997::vector द्वारा प्रतिस्थापित करें।

अगले मानक आओ, और एसटीएल विक्रेता बस फिर प्रक्रिया को दोहराता है, emplace_back समर्थन (जो सी ++ 11 की आवश्यकता है) के साथ std::vector के लिए एक नया नाम स्थान शुरू करने और इनलाइन करने __cplusplus == 201103L iff है कि एक।

ठीक है, तो मुझे इसके लिए एक नई भाषा सुविधा क्यों चाहिए? मैं पहले से ही एक ही प्रभाव के लिए निम्नलिखित कर सकता हूं, नहीं?

namespace std { 

    namespace pre_cxx_1997 { 
     // ... 
    } 
#if __cplusplus < 1997L // pre-standard C++ 
    using namespace pre_cxx_1997; 
#endif 

#if __cplusplus >= 1997L // C++98/03 or later 
         // (ifdef'ed out b/c it probably uses new language 
         // features that a pre-C++98 compiler would choke on) 

    namespace cxx_1997 { 
     // ... 
    }; 
# if __cplusplus == 1997L // C++98/03 
    using namespace cxx_1997; 
# endif 

#endif // C++98/03 or later 

} // namespace std 

__cplusplus के मूल्य पर निर्भर करता है, मैं या तो एक या कार्यान्वयन के अन्य मिलता है।

और आप लगभग सही होंगे।

पर विचार करें वैध सी ++ 98 उपयोगकर्ता कोड निम्नलिखित (यह पूरी तरह से विशेषज्ञ टेम्पलेट्स कि पहले से ही सी ++ 98 में नाम स्थान std में रहते हैं अनुमति दी गई थी):

// I don't trust my STL vendor to do this optimisation, so force these 
// specializations myself: 
namespace std { 
    template <> 
    class vector<MyType> : my_special_vector<MyType> { 
     // ... 
    }; 
    template <> 
    class vector<MyOtherType> : my_special_vector<MyOtherType> { 
     // ... 
    }; 
    // ...etc... 
} // namespace std 

यह पूरी तरह से वैध कोड है, जहां उपयोगकर्ता एक प्रकार के सेट के लिए वेक्टर के अपने कार्यान्वयन की आपूर्ति करता है जहां वह स्पष्ट रूप से एसटीएल की उसकी प्रति (उस की प्रतिलिपि) की तुलना में अधिक कुशल कार्यान्वयन जानता है।

लेकिन: जब एक टेम्पलेट विशेषज्ञता, आप नाम स्थान में घोषित किया गया था में ऐसा करने की जरूरत है मानक का कहना है कि vector, नाम स्थान std में घोषित किया जाता है तो यह है कि जहां उपयोगकर्ता हक प्रकार के विशेषज्ञ करने की उम्मीद है।।

इस कोड, एक गैर संस्करणीकृत नाम स्थान std साथ काम करता है, या सी ++ 11 इनलाइन नाम स्थान की सुविधा के साथ नहीं, बल्कि साथ संस्करण चाल कि using namespace <nested> इस्तेमाल किया क्योंकि कि कार्यान्वयन विस्तार यह सच नाम स्थान जिसमें vector था को उजागर करता है परिभाषित std सीधे नहीं था।

ऐसे अन्य छेद हैं जिनके द्वारा आप नेस्टेड नेमस्पेस का पता लगा सकते हैं (नीचे टिप्पणियां देखें), लेकिन इनलाइन नेमस्पेस उन सभी को प्लग करें। और यह सब कुछ है। भविष्य के लिए बेहद उपयोगी है, लेकिन मानक AFAKK अपने मानक पुस्तकालय के लिए इनलाइन नेमस्पेस नामों को निर्धारित नहीं करता है (हालांकि, मुझे इस पर गलत साबित होना अच्छा लगेगा), इसलिए इसका उपयोग केवल तृतीय-पक्ष पुस्तकालयों के लिए किया जा सकता है, न कि मानक स्वयं (जब तक संकलक विक्रेता नामकरण योजना पर सहमत नहीं होते)।

+13

+1 क्यों 'नेमस्पेस V99 का उपयोग करना;' स्ट्रॉस्ट्रप के उदाहरण में काम नहीं करता है। –

+2

मुझे लगता है कि एक मानक तरीके से मानक पुस्तकालयों में संस्करण, तीसरे पक्ष के संस्करण के मुकाबले सीमित है।यदि सी ++ 21 'वेक्टर' मेरे लिए अच्छा नहीं है, और मुझे सी ++ 11 'वेक्टर' की आवश्यकता है, तो यह सी ++ 21 में ब्रेकिंग बदलाव की वजह से हो सकता है। लेकिन यह एक कार्यान्वयन विस्तार के कारण हो सकता है कि मुझे पहले स्थान पर भरोसा नहीं करना चाहिए था। मानक की आवश्यकता नहीं हो सकती है कि प्रत्येक सी ++ 21 कार्यान्वयन एक 'std :: cxx_11 :: वेक्टर' प्रदान करता है जो एक ही विक्रेता से किसी भी पिछले' std :: vector' के साथ संगत बग है। तीसरे पक्ष के पुस्तकालय ऐसा करने के लिए कर सकते हैं, अगर उन्हें लगता है कि यह उनके लिए लायक है। –

+3

और इसी तरह, यदि मैं स्क्रैच से एक नया सी ++ 21 कार्यान्वयन शुरू करता हूं, तो मैं 'std :: cxx_11' में बहुत पुराने बकवास को लागू करने के लिए बोझ नहीं बनना चाहता हूं। प्रत्येक कंपाइलर हमेशा मानक पुस्तकालयों के सभी पुराने संस्करणों को लागू नहीं करेगा, भले ही यह सोचने के लिए इस समय लुभाना पड़ेगा कि पुराने कार्यान्वयन की आवश्यकता होने पर पुराने कार्यान्वयन की आवश्यकता होने पर बहुत कम बोझ होगा, क्योंकि वास्तव में वे सभी वैसे भी हैं मुझे लगता है कि मानक क्या उपयोगी ढंग से किया जा सकता है इसे वैकल्पिक बना दिया गया है, लेकिन यदि मौजूद है तो मानक नाम के साथ। –

52

http://www.stroustrup.com/C++11FAQ.html#inline-namespace (Bjarne Stroustrup द्वारा लिखित और रखरखाव वाला एक दस्तावेज़, जो आपको लगता है कि अधिकांश सी ++ 11 सुविधाओं के लिए सबसे अधिक प्रेरणा से अवगत होना चाहिए।)

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

दिए गए उदाहरण

है:

// file V99.h: 
inline namespace V99 { 
    void f(int); // does something better than the V98 version 
    void f(double); // new feature 
    // ... 
} 

// file V98.h: 
namespace V98 { 
    void f(int); // does something 
    // ... 
} 

// file Mine.h: 
namespace Mine { 
#include "V99.h" 
#include "V98.h" 
} 

#include "Mine.h" 
using namespace Mine; 
// ... 
V98::f(1); // old version 
V99::f(1); // new version 
f(1);  // default version 

मैं तुरंत नहीं दिख रहा है यही कारण है कि आप नाम स्थान Mine अंदर using namespace V99; डाल नहीं है, लेकिन मैं पूरी तरह यूज-केस को समझने के क्रम में लेने के लिए की जरूरत नहीं है समिति की प्रेरणा पर इसके लिए बजरने का शब्द।

+0

तो वास्तव में अंतिम 'एफ (1)' संस्करण इनलाइन 'वी 99' नामस्थान से कहा जाएगा? –

+1

@EitanT: हां, क्योंकि वैश्विक नामस्थान में 'नामस्थान खान का उपयोग करना' है, और 'माइन' नेमस्पेस में इनलाइन नेमस्पेस 'Mine :: V99' से सबकुछ शामिल है। –

+0

लेकिन इसके लिए काम करने के लिए, मुझे V99.h फ़ाइल करने के लिए 'इनलाइन' जोड़ना होगा। क्या होता है जब फ़ाइल V100.h आता है, 'इनलाइन नेमस्पेस V100' घोषित करता है, और मैं इसे' माइन 'में भी शामिल करता हूं? 'एफ (int)' किस 'एफ (1)' द्वारा बुलाया जाता है? – Walter

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

  • कोई संबंधित समस्या नहीं^_^