इनलाइन नेमस्पेस किसके लिए हैं?


334

C ++ 11 inline namespaces की अनुमति देता है , जिसके सभी सदस्य स्वतः संलग्नक में भी हैं namespace। मैं इसके किसी भी उपयोगी अनुप्रयोग के बारे में नहीं सोच सकता - क्या कोई ऐसी स्थिति का संक्षिप्त, संक्षिप्त उदाहरण दे सकता है, जहाँ inline namespaceइसकी आवश्यकता है और जहाँ यह सबसे मुहावरेदार समाधान है?

(इसके अलावा, यह मेरे लिए स्पष्ट नहीं है कि क्या होता है जब एक namespaceमें घोषित किया inlineजाता है, लेकिन सभी घोषणाएं नहीं होती हैं, जो अलग-अलग फाइलों में रह सकती हैं। क्या यह परेशानी के लिए भीख नहीं है?)

जवाबों:


339

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

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

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

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

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

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, मुझे या तो एक या अन्य कार्यान्वयन मिलते हैं।

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

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

// 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साथ, या C ++ 11 इनलाइन नामस्थान सुविधा के साथ काम करता है , लेकिन उपयोग की गई संस्करण की चाल के साथ नहीं using namespace <nested>, क्योंकि यह कार्यान्वयन विवरण को उजागर करता है जिसमें सही नाम स्थान vectorपरिभाषित नहीं किया गया था std

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


23
+1 यह समझाने के लिए कि using namespace V99;स्ट्रॉस्ट्रुप के उदाहरण में काम क्यों नहीं किया जाता है।
स्टीव जेसोप

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

46
यह सब वहाँ नहीं है। ADL भी एक कारण था (ADL निर्देशों का उपयोग नहीं करेगा), और नाम देखने का भी। ( using namespace Aएक नाम स्थान में बी नामस्थानों में नाम बनाता है बी नाम स्थान ए में नाम छिपाते हैं यदि आप खोजते हैं B::name- तो इनलाइन नामस्थान के साथ नहीं)।
जोहान्स शाउब -

4
ifdefपूर्ण सदिश कार्यान्वयन के लिए सिर्फ एस का उपयोग क्यों न करें ? सभी कार्यान्वयन एक नामस्थान में होंगे, लेकिन उनमें से केवल एक को प्रीप्रोसेसिंग के बाद परिभाषित किया जाएगा
sasha.sochka

6
@ sasha.sochka, क्योंकि इस मामले में आप अन्य कार्यान्वयन का उपयोग नहीं कर सकते। उन्हें प्रीप्रोसेसर द्वारा हटा दिया जाएगा। इनलाइन नेमस्पेस के साथ आप पूरी तरह से योग्य नाम (या usingकीवर्ड) निर्दिष्ट करके किसी भी कार्यान्वयन का उपयोग कर सकते हैं ।
वासिली बिरुकोव

70

http://www.stroustrup.com/C+11FAQ.html#inline-namespace (Bjarne Stroustrup द्वारा लिखित और अनुरक्षित एक दस्तावेज, जो आपको लगता है कि अधिकांश C ++ 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

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


तो वास्तव f(1)में इनलाइन V99नेमस्पेस से अंतिम संस्करण कहा जाएगा ?
Eitan T

1
@ EitanT: हाँ, क्योंकि वैश्विक नामस्थान में है using namespace Mine;, और Mineनामस्थान में इनलाइन नामस्थान से सब कुछ है Mine::V99
स्टीव जेसोप

2
@Walter: आप रिलीज़ में inlineफ़ाइल से हटाते हैं V99.hजिसमें शामिल हैं V100.h। आप Mine.hएक ही समय में, एक अतिरिक्त जोड़ने के लिए भी संशोधित करते हैं। Mine.hलाइब्रेरी का हिस्सा है, क्लाइंट कोड का हिस्सा नहीं है।
स्टीव जेसोप

5
@walter: वे स्थापित नहीं कर रहे हैं V100.h, वे "मेरा" नामक एक पुस्तकालय स्थापित कर रहे हैं। - "मेरा" का संस्करण 99 में 3 हेडर फाइल कर रहे हैं Mine.h, V98.hऔर V99.h। - "मेरा" का संस्करण 100 में 4 हेडर फाइल कर रहे हैं Mine.h, V98.h, V99.hऔर V100.h। हेडर फ़ाइलों की व्यवस्था एक कार्यान्वयन विवरण है जो उपयोगकर्ताओं के लिए अप्रासंगिक है। यदि उन्हें कुछ संगतता समस्या का पता चलता है, जिसका अर्थ है कि उन्हें Mine::V98::fअपने कोड के कुछ या सभी से विशेष रूप से उपयोग करने की आवश्यकता है , तो वे Mine::V98::fपुराने कोड से कॉल को Mine::fनए-लिखित कोड में कॉल के साथ मिला सकते हैं ।
स्टीव जेसोप

2
@ अन्य जवाब के रूप में, टेम्प्लेट को उनके द्वारा घोषित नामस्थान में विशेषीकृत करने की आवश्यकता होती है, न कि वे जो वे घोषित किए गए हैं, का उपयोग करते हुए कोई नामस्थान नहीं है। जबकि यह अजीब लगता है, जिस तरह से यह वहां किया गया है जो आपको टेम्प्लेट को विशेषज्ञ करने की अनुमति देता है। Mineके बजाय में विशेषज्ञ Mine::V99या होने के लिए Mine::V98
जस्टिन टाइम -

8

अन्य सभी उत्तरों के अतिरिक्त।

इनलाइन नेमस्पेस का उपयोग एबीआई जानकारी या प्रतीकों में कार्यों के संस्करण को एनकोड करने के लिए किया जा सकता है। यह इस कारण से है कि उनका उपयोग पिछड़े एबीआई संगतता प्रदान करने के लिए किया जाता है। इनलाइन नेमस्पेस आपको एपीआई को परिवर्तित किए बिना मंगली नाम (एबीआई) में जानकारी इंजेक्ट करते हैं क्योंकि वे केवल लिंकर प्रतीक नाम को प्रभावित करते हैं।

इस उदाहरण पर विचार करें:

मान लीजिए आप एक फ़ंक्शन लिखते हैं जो Fooकिसी ऑब्जेक्ट के संदर्भ में कहता है barऔर कुछ भी नहीं देता है।

मुख्य कहो

struct bar;
void Foo(bar& ref);

यदि आप किसी ऑब्जेक्ट में कंपाइल करने के बाद इस फाइल के लिए अपना सिंबल नाम चेक करते हैं।

$ nm main.o
T__ Z1fooRK6bar 

लिंकर का प्रतीक नाम अलग-अलग हो सकता है, लेकिन यह निश्चित रूप से फ़ंक्शन और तर्क प्रकारों के नाम को कहीं न कहीं एनकोड करेगा।

अब, यह हो सकता है कि barके रूप में परिभाषित किया गया है:

struct bar{
   int x;
#ifndef NDEBUG
   int y;
#endif
};

बिल्ड प्रकार पर निर्भर करता है, barएक ही लिंकर प्रतीकों के साथ दो अलग-अलग प्रकार / लेआउट को संदर्भित कर सकता है।

इस तरह के व्यवहार को रोकने के लिए हम अपनी संरचना barको इनलाइन नेमस्पेस में लपेटते हैं , जहां बिल्ड प्रकार के आधार पर लिंकर का प्रतीक barअलग होगा।

तो, हम लिख सकते हैं:

#ifndef NDEBUG
inline namespace rel { 
#else
inline namespace dbg {
#endif
struct bar{
   int x;
#ifndef NDEBUG
   int y;
#endif
};
}

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

$ nm rel.o
T__ ZROKfoo9relEbar
$ nm dbg.o
T__ ZROKfoo9dbgEbar

लिंकर प्रतीक नाम अलग हो सकते हैं।

relऔर dbgप्रतीक नामों में उपस्थिति की सूचना ।

अब, यदि आप डिबग को रिलीज़ मोड या vise-versa से लिंक करने का प्रयास करते हैं, तो आपको रनटाइम त्रुटि के विपरीत एक लिंकर त्रुटि मिलेगी।


1
हाँ, यह समझ में आता है। तो यह पुस्तकालय कार्यान्वयनकर्ताओं और पसंद के लिए अधिक है।
वाल्टर

3

मैंने वास्तव में इनलाइन नेमस्पेस के लिए एक और उपयोग की खोज की।

क्यूटी के साथ , आपको कुछ अतिरिक्त, अच्छी सुविधाओं का उपयोग करने की सुविधा मिलती है Q_ENUM_NS, जिसके बदले एनक्लोजिंग नेमस्पेस में एक मेटा-ऑब्जेक्ट होता है, जिसे साथ घोषित किया जाता है Q_NAMESPACE। हालांकि, Q_ENUM_NSकाम करने के लिए, एक Q_NAMESPACE ही फाइल में संगत होना चाहिए to। और केवल एक ही हो सकता है, या आपको डुप्लिकेट परिभाषा त्रुटियां मिलती हैं। इसका प्रभावी रूप से मतलब है कि आपके सभी गणनाओं को एक ही शीर्ष लेख में होना चाहिए। छी।

या ... आप इनलाइन नेमस्पेस का उपयोग कर सकते हैं। inline namespaceमेटा-ऑब्जेक्ट के अलग-अलग नाम होने के कारणएन्यूमरेशन छिपाते हैं, जबकि उपयोगकर्ताओं के लिए अतिरिक्त नामस्थान मौजूद नहीं होते हैं।

तो, वे कई उप-नामस्थानों में सामानों को विभाजित करने के लिए उपयोगी हैं जो सभी एक नामस्थान की तरह दिखते हैं, यदि आपको किसी कारण से ऐसा करने की आवश्यकता है। बेशक, यह using namespace innerबाहरी नामस्थान में लिखने के समान है , लेकिन डीआरवाई के बिना आंतरिक नामस्थान के नाम को दो बार लिखने के उल्लंघन के बिना ।


  1. यह वास्तव में इससे भी बदतर है; यह ब्रेसिज़ के एक ही सेट में होना है।

  2. जब तक आप मेटा-ऑब्जेक्ट को पूरी तरह से योग्य किए बिना एक्सेस करने का प्रयास नहीं करते हैं, लेकिन मेटा-ऑब्जेक्ट शायद ही कभी सीधे उपयोग किया जाता है।


आप कोड के एक कंकाल के साथ स्केच कर सकते हैं? (आदर्श रूप से w / o Qt का स्पष्ट संदर्भ)। यह सब बल्कि शामिल / अस्पष्ट लगता है।
वाल्टर

आसानी से नहीं। अलग नामस्थानों की आवश्यकता है क्यूटी कार्यान्वयन विवरण के साथ क्या करना है। टीबीएच, क्यूटी के बाहर की स्थिति की कल्पना करना मुश्किल है जिसकी समान आवश्यकताएं होंगी। हालाँकि, इस Qt- विशिष्ट परिदृश्य के लिए, वे उपयोगी हैं! उदाहरण के लिए gist.github.com/mwoehlke-kitware/… या github.com/Kitware/seal-tk/pull/45 देखें ।
मैथ्यू

0

तो मुख्य बिंदुओं को समेटने के लिए, using namespace v99और inline namespaceसमान नहीं थे, पूर्व में संस्करण पुस्तकालयों में एक समर्पित कीवर्ड (इनलाइन) को C ++ 11 में पेश किया गया था जो usingएक ही संस्करण की कार्यक्षमता प्रदान करते हुए उपयोग करने की समस्याओं को ठीक करता है। using namespaceADL के साथ समस्याओं का उपयोग करने के लिए उपयोग किया जाता है (हालांकि ADL अब usingनिर्देशों का पालन करता प्रतीत होता है ), और उपयोगकर्ता द्वारा किसी लाइब्रेरी क्लास / फंक्शन आदि की आउट-ऑफ-लाइन विशेषज्ञता सही नामस्थान (जिसका नाम है, के बाहर काम नहीं करेगा) उपयोगकर्ता नहीं जानता है और न ही होना चाहिए, अर्थात उपयोगकर्ता को B :: abi_v2 :: का उपयोग केवल विशेषज्ञता के लिए B: के बजाय करने के लिए करना होगा।

//library code
namespace B { //library name the user knows
    namespace A { //ABI version the user doesn't know about
        template<class T> class myclass{int a;};
    }
    using namespace A; //pre inline-namespace versioning trick
} 

// user code
namespace B { //user thinks the library uses this namespace
    template<> class myclass<int> {};
}

यह एक स्थिर विश्लेषण चेतावनी दिखाएगा first declaration of class template specialization of 'myclass' outside namespace 'A' is a C++11 extension [-Wc++11-extensions]। लेकिन अगर आप नेमस्पेस ए इनलाइन बनाते हैं, तो संकलक विशेषज्ञता को सही ढंग से हल करता है। हालाँकि, C ++ 11 एक्सटेंशन के साथ, समस्या दूर हो जाती है।

उपयोग करते समय आउट-ऑफ-लाइन परिभाषाएँ हल नहीं होती हैं using; उन्हें एक नेस्टेड / नॉन-नेस्टेड एक्सटेंशन नेमस्पेस ब्लॉक में घोषित किया जाना है (जिसका अर्थ है कि उपयोगकर्ता को एबीआई संस्करण को फिर से जानना होगा, यदि किसी भी कारण से उन्हें फ़ंक्शन के अपने कार्यान्वयन को प्रदान करने की अनुमति दी गई थी)।

#include <iostream>
namespace A {
    namespace B{
        int a;
        int func(int a);
        template<class T> class myclass{int a;};
        class C;
        extern int d;
    } 
    using namespace B;
} 
int A::d = 3; //No member named 'd' in namespace A
class A::C {int a;}; //no class named 'C' in namespace 'A' 
template<> class A::myclass<int> {}; // works; specialisation is not an out-of-line definition of a declaration
int A::func(int a){return a;}; //out-of-line definition of 'func' does not match any declaration in namespace 'A'
namespace A { int func(int a){return a;};} //works
int main() {
    A::a =1; // works; not an out-of-line definition
}

B इनलाइन बनाते समय समस्या दूर हो जाती है।

अन्य कार्यक्षमता inlineनामस्थानों में पुस्तकालय लेखक को पुस्तकालय 1 को पारदर्शी अद्यतन प्रदान करने की अनुमति है) नए नामस्थान नाम और 2 के साथ रिफ्लेक्टर कोड के लिए उपयोगकर्ता को मजबूर किए बिना क्रिया की कमी और 3) एपीआई-अप्रासंगिक विवरणों के अमूर्तता प्रदान करने से रोकता है। 4) whilst एक ही लाभकारी लिंकर निदान और व्यवहार है कि एक गैर इनलाइन नाम स्थान का उपयोग कर प्रदान करेगा। मान लीजिए कि आप एक पुस्तकालय का उपयोग कर रहे हैं:

namespace library {
    inline namespace abi_v1 {
        class foo {
        } 
    }
}

यह उपयोगकर्ता को library::fooदस्तावेज में एबीआई संस्करण को जानने या शामिल किए बिना कॉल करने की अनुमति देता है , जो क्लीनर दिखता है। इस्तेमाल करने से library::abiverison129389123::fooगंदा लगेगा।

जब एक अद्यतन किया जाता है foo, अर्थात कक्षा में एक नया सदस्य जोड़ रहा है, तो यह एपीआई स्तर पर मौजूदा कार्यक्रमों को प्रभावित नहीं करेगा क्योंकि वे पहले से ही सदस्य का उपयोग नहीं करेंगे और इनलाइन नेमस्पेस नाम में परिवर्तन एपीआई स्तर पर कुछ भी नहीं बदलेगा। क्योंकि library::fooअभी भी काम करेगा।

namespace library {
    inline namespace abi_v2 {
        class foo {
            //new member
        } 
    }
}

हालाँकि, इसके साथ लिंक करने वाले कार्यक्रमों के लिए, क्योंकि इनलाइन नेमस्पेस नाम को एक नियमित नामस्थान जैसे प्रतीक नामों में जोड़ दिया जाता है, परिवर्तन लिंकर के लिए पारदर्शी नहीं होगा। इसलिए, यदि एप्लिकेशन को पुन: कनेक्ट नहीं किया गया है, लेकिन लाइब्रेरी के एक नए संस्करण के साथ जुड़ा हुआ है, तो यह एक प्रतीक प्रस्तुत करेगा जिसमें abi_v1त्रुटि नहीं पाई जा रही है, बजाय इसके कि यह वास्तव में लिंक कर रहा है और फिर एबीआई असंगति के कारण रनटाइम पर एक रहस्यमय तर्क त्रुटि पैदा करता है। नए सदस्य को जोड़ने से टाइप परिभाषा में परिवर्तन के कारण एबीआई संगतता हो जाएगी, भले ही यह संकलन समय (एपीआई स्तर) पर कार्यक्रम को प्रभावित न करे।

इस परिदृश्य में:

namespace library {
    namespace abi_v1 {
        class foo {
        } 
    }

    inline namespace abi_v2 {
        class foo {
            //new member
        } 
    }
}

2 गैर-इनलाइन नामस्थानों का उपयोग करने की तरह, यह लाइब्रेरी के एक नए संस्करण को एप्लिकेशन को फिर से खोलने की आवश्यकता के बिना लिंक करने की अनुमति देता है, क्योंकि abi_v1वैश्विक प्रतीकों में से एक में मंगाई जाएगी और यह सही (पुरानी) प्रकार की परिभाषा का उपयोग करेगा। हालांकि आवेदन को फिर से जमा करना संदर्भों को हल करने का कारण होगा library::abi_v2

प्रयोग करने using namespaceसे कम कार्यात्मक है inline( का उपयोग उस में से बाहर लाइन परिभाषाएँ हल नहीं) लेकिन ऊपर के रूप में एक ही 4 लाभ प्रदान करता है। लेकिन असली सवाल यह है कि जब इसे करने के लिए कोई समर्पित कीवर्ड है तो वर्कअराउंड का उपयोग क्यों जारी रखें। यह बेहतर अभ्यास है, कम क्रिया (2 के बजाय कोड की 1 पंक्ति को बदलना है) और इरादा स्पष्ट करता है।

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