2015-08-25 6 views
24

इस कोड पर विचार करें:एक इनलाइन नेमस्पेस मौजूद होने पर मैं स्पष्ट रूप से एक संलग्न नामस्थान का संदर्भ कैसे दे सकता हूं?

#include <iostream> 

namespace Foo{ 

    void ool() // Version A 
    { 
     std::cout << "Foo::ool" << std::endl; 
    } 

    inline namespace Bar{ 
     void ool() // Version B 
     { 
      std::cout << "Foo::Bar::ool" << std::endl; 
     } 
    } 
} 


int main() 
{ 
    Foo::ool(); // <- error 
} 

दोनों बजना और जी ++ सही ढंग से Foo::ool के रूप में अस्पष्ट निशान। मैं समस्या के बिना Foo::Bar::ool पर कॉल कर सकता हूं लेकिन क्या संस्करण घोषणा को बिना किसी घोषणा के कॉल करने का कोई तरीका है?

मैंने लोगों को यह समझने की कोशिश कर रहे समान स्थिति में पाया लेकिन मुझे इस मामले का समाधान नहीं मिला।

मैं इस स्थिति में हूं क्योंकि मेरे पास एक परियोजना है जिसमें std::__1::pair और std::pair की घोषणा शामिल है, जो विभिन्न स्थानों पर बनाई गई है, std::__1 इनलाइन नेमस्पेस होने के साथ। मुझे स्पष्ट रूप से std::pair पर इंगित करने के लिए कोड की आवश्यकता है। क्या इसके लिए कोई समाधान है?

+1

शायद __1 :: जोड़ी को प्रस्तुत करने से पहले एक उपनाम टेम्पलेट को परिभाषित करता है जो std :: pair को संदर्भित करता है? – Columbo

+3

क्या आप वाकई [इस समस्या] को देख रहे हैं (http://stackoverflow.com/questions/9000816/libc-stop-std-renaming-to-std-1)? (मूल रूप से, समाधान संकलन विकल्पों में '-std = C++ 0x' (या नए कंपाइलर्स के समान) जोड़ना होगा।) आप किस कंपाइलर संस्करण और सेटिंग्स का उपयोग कर रहे हैं? – utnapistim

+0

utnapistim: आप सही हैं। मुझे अपने विशिष्ट मामले के लिए इस कामकाज का सामना करना पड़ा था, लेकिन मुझे सामान्य मामले में इस विशिष्ट अस्पष्टता को हल करने के बारे में उत्सुकता मिली। मुझे लगता है कि समाधान मेरे मामले में std = libstdC++ में अधिक झूठ बोला लेकिन यह मेरे संकलन मुद्दों को हल किया, धन्यवाद! – YvesQuemener

उत्तर

12

मुझे नहीं लगता कि यह संभव है;

योग्य नाम देखने की जांच करता है कि संलग्न नाम स्थान इनलाइन नामस्थान से नाम शामिल होंगे, भले ही एक ही नाम संलग्न नाम स्थान में मौजूद है: cppreference से।

हालांकि, ऐसा लगता है कि आप वास्तव में स्थिति में नहीं हैं, जैसा कि आप कहते हैं कि दो परिभाषाओं को विभिन्न फाइलों से खींचा जाता है। इस प्रकार आप "बुकमार्क" क्रम में अधिक बाहरी परिभाषा यह कॉल कर सकते हैं जब आप इसकी आवश्यकता होने के लिए:

#include <iostream> 

// Equivalent of first include 
namespace Foo{ 
    void ool() // Version A 
    { 
     std::cout << "Foo::ool" << std::endl; 
    } 
} 

const auto& foo_ool = Foo::ool; 

// Equivalent of second include 
namespace Foo{ 
    inline namespace Bar{ 
     void ool() // Version B 
     { 
      std::cout << "Foo::Bar::ool" << std::endl; 
     } 
    } 
} 

int main() 
{ 
    foo_ool(); // Works 
} 

तो बात आप बुकमार्क करना चाहते एक प्रकार है, एक सरल using निर्देश पर्याप्त होना चाहिए। आपके लिए समकक्ष कोड इस तरह दिखेगा:

#include <my_first_include> 

// bookmark code 

#include <my_second_include> 

// rest of the code 
+0

धन्यवाद। मुझे यह अजीब लगता है कि संकलक चुपचाप एक नई रेखांकित परिभाषा के साथ कक्षा को अधिभारित करने के लिए स्वीकार करेगा। संलग्न नामस्थान में Foo :: ool फ़ंक्शन पूरी तरह से अटूट हो जाता है। ऐसा लगता है कि इस व्यवहार को कम से कम एक चेतावनी ट्रिगर करना चाहिए। लेकिन बुकमार्किंग चाल के लिए धन्यवाद। इस समस्या के समाधान के लिए यह निकटतम है। – YvesQuemener

2

मुझे नहीं लगता कि आप ool अस्पष्ट रूप से संदर्भित कर सकते हैं जब एक इनलाइन नेमस्पेस के पास एक ही नाम ool के साथ एक विधि है।

लेकिन आप इसे आजमा सकते हैं; एक namespace A तो inlinenamespace A में namespace Foo में

#include <iostream> 

namespace Foo{ 

    inline namespace A { 
     void ool() // Version A 
     { 
      std::cout << "Foo::ool" << std::endl; 
     } 
    } 

    namespace Bar{ 
     void ool() // Version B 
     { 
      std::cout << "Foo::Bar::ool" << std::endl; 
     } 
    } 
} 


int main() 
{ 
    Foo::ool(); // no error 
} 
  1. लपेटें तरीकों।
  2. Bar से इनलाइन निकालें।

अब आप इसे लागू करेगा inline A::ool()
Bar::oolFoo::Bar::ool

5

एक बार इनलाइन नाम स्थान में देखा गया है आप स्पष्ट रूप से प्रतीक संलग्नित नाम स्थान में परिभाषित करने का उल्लेख नहीं कर सकते द्वारा लागू किया जा सकता है एक फोन Foo::ool(); करते हैं।

विशेष रूप से आपके मामले में, main में योग्य खोज योग्यता को अस्पष्ट होने के रूप में चिह्नित किया गया है (जैसा आपने स्वयं कहा था)। cppreference पर अंतिम बिंदु देखें:

योग्य नाम लुकअप कि संलग्नित नाम स्थान इनलाइन नामस्थान से नाम शामिल होंगे, भले ही एक ही नाम संलग्न नाम स्थान में मौजूद है जांच करता है।


फिर भी, अन्य टिप्पणी में बताया है, आप शायद अपने toolchain मंगलाचरण में विन्यास की एक समस्या का सामना कर रहे आप std::pair का उपयोग करने का प्रयास करते।

-std=c++11 या -std=c++0x बजना/जीसीसी

के अपने संस्करण के आधार पर:

आप समस्या को ठीक करने के लिए, आप सुनिश्चित करें कि संकलक सी ++ 11 कोड है, जो ध्वज के साथ होगा संकलित करने के लिए शुरू हो जाती है बनाने की जरूरत है

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

+0

हां मैंने वास्तव में इस तरह की वर्तमान समस्या हल की है, लेकिन मैं सोच रहा था कि इसे और अधिक सामान्य तरीके से कैसे हल किया जाए। वैसे भी इन्हें इंगित करने के लिए धन्यवाद। – YvesQuemener

+1

@YvesQuemener अर्थात्, आपको * संलग्न * प्रतीक तक पहुंचने की आवश्यकता नहीं है: यदि आपके पास वास्तव में एक ही नाम (मोडुलो ओवरलोडिंग) एक ही नामस्थान में कई बार परिभाषित किया गया है (सीधे लिखा गया है, घोषणाओं का उपयोग करके, या इनलाइन नामस्थान के माध्यम से) , समस्या कई घोषणाएं हैं, न कि उनके आसपास कैसे काम करें:) –

+0

हां, लेकिन यदि समस्या इस तथ्य में निहित है कि प्रतीक ओवरलोड हो जाते हैं, तो ऐसा होने पर संकलक इसके बारे में चेतावनी क्यों नहीं देता है? आखिरकार, यह एक ही दायरे में डुप्लिकेट परिभाषा के साथ एक त्रुटि जारी करता है। – YvesQuemener

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

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