2009-07-26 17 views
17

वहाँ एक मानकstack, queue, priority_queue के अंतर्निहित कंटेनर का उपयोग करने के तरीका है? stack और queue की VS2008 कार्यान्वयन में _Get_container(), लेकिन priority_queue के लिए कोई भी:क्या एसटीएल कंटेनर एडेप्टर के अंतर्निहित कंटेनर तक पहुंचने का कोई तरीका है?

मैं एक विधि कहा जाता है मिल गया! मुझे लगता है कि यह वैसे भी मानक नहीं है।

इसके अलावा, मुझे पता है कि यह एक मूर्ख सवाल है! मुझे मानक पुस्तकालय के आधिकारिक दस्तावेज कहां मिल सकता है?


बस स्पष्टीकरण के लिए, मैं अंतर्निहित कंटेनर के साथ गड़बड़ करने की कोशिश नहीं कर रहा था।

template <class Container> 
std::ostream& printOneValueContainer(std::ostream& outputstream, Container& container) 
{ 
    Container::const_iterator beg = container.begin(); 

    outputstream << "["; 

    while(beg != container.end()) 
    { 
     outputstream << " " << *beg++; 
    } 

    outputstream << " ]"; 

    return outputstream; 
} 

// stack, queue 
template 
    < class Type 
    , template<class Type, class Container = std::deque<Type> > class Adapter 
    > 
std::ostream& operator<<(std::ostream& outputstream, const Adapter<Type>& adapter) 
{ 
    return printOneValueContainer(outputstream, adapter._Get_container()); 
} 
. 
. 
. 
std::stack<int> iStack; 
. 
. 
std::cout << iStack << std::endl; 

मुझे आशा है कि आप देखते हैं कि _Get_container() मानक नहीं है, और वहाँ VS2008 कार्यान्वयन में priority_queue के लिए कोई नहीं है: सभी मैं क्या करने की कोशिश कर रहा था यह है।

+0

आप वास्तव में क्या जरूरत नहीं है, लेकिन कतार/ढेर/priority_queue सब एक ** संरक्षित ** सदस्य 'c' जो अंतर्निहित कंटेनर है, इसलिए यदि आप इनमें से किसी से विरासत, आप इसे उपयोग कर सकते हैं है सीधे । –

+0

@ ईवन दिलचस्प! क्या इसका मतलब यह है कि एडेप्टर विरासत के माध्यम से विस्तार के लिए लक्षित हैं? यदि हां, तो वर्चुअल डॉटर क्यों नहीं? –

+0

इसके अलावा, संरक्षित डेटा मेरी पुस्तक में नो-नो है - मैं इससे थोड़ा निराश हूं! –

उत्तर

14

मैं वेब पर कहीं निम्नलिखित समाधान देखा है और मैं इसे उपयोग कर रहा हूँ अपनी परियोजनाओं में:

template <class T, class S, class C> 
    S& Container(priority_queue<T, S, C>& q) { 
     struct HackedQueue : private priority_queue<T, S, C> { 
      static S& Container(priority_queue<T, S, C>& q) { 
       return q.*&HackedQueue::c; 
      } 
     }; 
    return HackedQueue::Container(q); 
} 

int main() 
{ 
    priority_queue<SomeClass> pq; 
    vector<SomeClass> &tasks = Container(pq); 
    return 0; 
} 

है मज़ा :)।

+0

मुझे यह हैक आदमी पसंद है। धन्यवाद ;) – AraK

3

नहीं, ऐसा करने का कोई मानक तरीका नहीं है। मानक तक पहुंच के लिए, यह वेब पर उपलब्ध नहीं है, आपको एक प्रति खरीदना होगा! हालांकि, ड्राफ्ट available here की विभिन्न प्रतियां हैं।

+0

थानक्स नील, मुझे लगता है कि मैं प्रलेखन खरीदूंगा :) – AraK

1

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

एसटीएल के दस्तावेज़ीकरण के लिए, आप एसजीआई के एसटीएल here के दस्तावेज़ीकरण को देख सकते हैं। एसजीआई के एसटीएल और सी ++ मानक में से एक के बीच कुछ अंतर हैं, लेकिन वे ज्यादातर उस साइट पर ध्यान दिए जाते हैं। इसके अलावा, सी ++ लाइब्रेरी का विकी दस्तावेज है जो अधिक पूर्ण हो रहा है।

+0

मैं आपका पॉइंट देखता हूं। जो मैं करने की कोशिश कर रहा हूं वह एक सामान्य कार्य लिख रहा है जो ढेर, कतार और प्राथमिकता_क्यू की सामग्री को स्ट्रीम करता है। यह सिर्फ मजेदार है इसलिए कोई समस्या नहीं :) – AraK

2

This SGI page ऑनलाइन उपलब्ध सबसे अधिक "आधिकारिक" दस्तावेज है, मुझे विश्वास है।

कारण यह है कि आप अंतर्निहित कंटेनर तक सीधे पहुंच प्राप्त नहीं कर सकते हैं यह है कि एडाप्टर उपयोग पैटर्न को बदलता है, और अंतर्निहित कंटेनर के तरीके उपलब्ध होने से उस नए उपयोग पैटर्न का उल्लंघन होगा। उदाहरण के लिए:

2 यह प्रतिबंध कतार के लिए एकमात्र कारण है। कोई भी कंटेनर जो फ्रंट सम्मिलन अनुक्रम और बैक सम्मिलन अनुक्रम दोनों होता है, को कतार के रूप में उपयोग किया जा सकता है; डेक, उदाहरण के लिए, सदस्य फ़ंक्शंस फ्रंट, बैक, पुश_फ्रंट, पुश_बैक, पॉप_फ्रंट और पॉप_बैक कंटेनर डेक के बजाय कंटेनर एडाप्टर कतार का उपयोग करने का एकमात्र कारण यह स्पष्ट करना है कि आप केवल कतार संचालन कर रहे हैं, और कोई अन्य नहीं संचालन। http://www.sgi.com/tech/stl/queue.html

आप डिजाइन की इस विशेषता के आसपास प्राप्त करना चाहते हैं, तो आप की तरह कुछ कर सकते हैं:

template <typename T> 
class clearable_queue : public std::queue<T> 
{ 
public: 
    void clear() { c.clear(); } 
}; 
+0

आमतौर पर आपको उनसे प्राप्त करने के बजाय कंटेनर लिखना चाहिए। उदाहरण के लिए, उनके पास वर्चुअल विनाशक नहीं हैं। – GManNickG

+0

सहमत हुए। हालांकि इस मामले में हम विनाशकों की परवाह नहीं करते हैं, और विरासत का उपयोग करके हम 'कतार' इंटरफ़ेस को प्रॉक्सी विधियों के रूप में परिभाषित करने से बचते हैं। –

2

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

दस्तावेज़ीकरण कहां खोजें, यह कई हिस्सों में विभाजित है।

आधिकारिक स्रोत, निश्चित रूप से, भाषा मानक है। जैसा कि नील बटरवर्थ ने कहा, मुफ्त ऑनलाइन के लिए मसौदा प्रतियां उपलब्ध हैं (जो अभी भी बहुत उपयोगी हैं। अंतिम संस्करण से अंतर वास्तव में न्यूनतम हैं)। वैकल्पिक रूप से, आप एक प्रति खरीद सकते हैं। यह जो भी संगठन आपके देश में आईएसओ का प्रतिनिधित्व करता है (और संभवतः एक अरब अन्य स्रोतों से भी) से उपलब्ध होना चाहिए। जिस दस्तावेज़ को आप ढूंढ रहे हैं वह ISO/IEC 14882:2003 Programming Language C++ है। (14882 मानक संख्या है। 2003 अंतिम संशोधन का वर्ष है। यदि आप 1 99 8 के संस्करण में आते हैं, तो आप इसका भी उपयोग कर सकते हैं। मतभेद वास्तव में दोनों के बीच हास्यास्पद रूप से छोटे हैं, और मूल रूप से केवल कुछ स्पष्टीकरणों की मात्रा है। शायद सी ++ 0x के लिए ड्राफ्ट से दूर रहने के लिए सबसे अच्छा है, क्योंकि वहां परिवर्तन अधिक व्यापक हैं)

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

माइक्रोसॉफ्ट के विस्तृत दस्तावेज MSDN पर उपलब्ध हैं। दस्तावेज मानक का सम्मान करता है, और स्पष्ट रूप से सभी गैर-मानक एक्सटेंशन को चिह्नित करता है ताकि आप जान सकें कि कौन सा है।

SGI में ऑनलाइन दस्तावेज़ भी है (हालांकि यह पुराना है और कुछ मामलों में, पूरी तरह से सटीक नहीं है)।

आईबीएम की वेबसाइट पर समान दस्तावेज उपलब्ध है, और मेरा मानना ​​है कि जीसीसी भी करता है।

+0

धन्यवाद आधा उपयोगी था :) – AraK

+0

ओह, यह भी नहीं पता था कि यह आपका प्रश्न था। सोचा था कि आप पहले से ही यह सामान जानते थे। ;) – jalf

-2

मुझे मानक पुस्तकालय का आधिकारिक दस्तावेज़ीकरण कहां मिल सकता है?

सी ++ मानक हार्डकवर में उपलब्ध है, आईएसबीएन 0470846747. स्टैंडर्ड का ड्राफ्ट PDF के रूप में व्यापक रूप से उपलब्ध हैं, लेकिन आप उन्हें आधिकारिक संस्करण (सी ++ 98,03 के साथ मैच के लिए सावधान रहना होगा, 11 या 14)। वर्तमान ड्राफ्ट सी ++ 14 मानक से अधिक है।

7

मैंने इसे एक टिप्पणी में वर्णित किया, लेकिन कुछ सोचने के बाद यह एक ठीक समाधान प्रतीत होता है। queue/stack/priority_queue (यानी, सभी एडाप्टर कक्षाएं) सभी में protected सदस्य c है जो अंतर्निहित कंटेनर है (आईएसओ/आईईसी 14882: 2003 खंड 23.2.2.4 देखें), इसलिए यदि आप इनमें से किसी से भी प्राप्त करते हैं, तो आप इसे सीधे एक्सेस कर सकते हैं।

मुझे पता है कि विशिष्ट ज्ञान गैर-आभासी dtors के कारण एसटीएल कंटेनरों से प्राप्त नहीं है, लेकिन यह मामला एक अपवाद है। लक्ष्य कार्यक्षमता अधिभारित नहीं है, लेकिन एडाप्टर के इंटरफेस में मामूली एक्सटेंशन बनाने के लिए है। अंतर्निहित कंटेनर तक पहुंचने की क्षमता जोड़ने का एक उदाहरण यहां दिया गया है।

#include <queue> 
#include <iostream> 

template <class Container> 
class Adapter : public Container { 
public: 
    typedef typename Container::container_type container_type; 
    container_type &get_container() { return this->c; } 
}; 

int main() { 
    typedef std::queue<int> C; 
    typedef Adapter<C> Container; 

    Container adapter; 

    for(int i = 0; i < 10; ++i) { 
     adapter.push(i); 
    } 

    Container::container_type &c = adapter.get_container(); 
    for(Container::container_type::iterator it = c.begin(); it != c.end(); ++it) { 
     std::cout << *it << std::endl; 
    } 
} 

दुर्भाग्य से, आपके द्वारा लिखे जाने-punning करने के लिए बिना प्रकार punning एक Adapter<std::queue<int> > * के लिए एक मौजूदा std::queue<int> * "अपग्रेड" सहारा होगा। तकनीकी तौर पर, यह संभावना ठीक काम करेगा ... लेकिन मैं इसके खिलाफ सलाह देते:

typedef std::stack<int> C; 
    typedef Adapter<C> Container; 
    C stack; 
    // put stuff in stack 
    Container *adapter = reinterpret_cast<Container *>(&stack); 
    Container::container_type &c = adapter->get_container(); 
    // from here, same as above   

तो मैं यह दोनों के बीच स्वैप करने के लिए आसान बनाने के लिए typedefs का उपयोग कर की सिफारिश करेंगे। (मेरे उदाहरण में भी ध्यान दें कि typedef एस के उदार उपयोग के कारण आपको queue से stack पर बदलने के लिए केवल 1 पंक्ति को बदलने की आवश्यकता है।

3

accepted answer के आधार पर, एक अधिक सामान्य दृष्टिकोण:

template <class ADAPTER> 
typename ADAPTER::container_type & get_container (ADAPTER &a) 
{ 
    struct hack : ADAPTER { 
     static typename ADAPTER::container_type & get (ADAPTER &a) { 
      return a.*&hack::c; 
     } 
    }; 
    return hack::get(a); 
} 

जैसा कि मैंने this answer से सीखा, .*& वास्तव में दो ऑपरेटरों, जहां सूचक &hack::c से उत्पन्न (ADAPTER::container_type ADAPTER::* टाइप किया है जो) लक्ष्य या है अंतर्निहित कंटेनर को पुनः प्राप्त करने के लिए .* ऑपरेटर। hack में संरक्षित सदस्य तक पहुंच है, लेकिन पॉइंटर प्राप्त होने के बाद, सुरक्षा खो जाती है। तो a.*(&hack::c) की अनुमति है।

0

सदस्य चर सी प्राप्त करने के लिए आप उप-वर्ग लिख सकते हैं। libstdC++ से यह टिप्पणी देखें।

protected: 
/** 
* 'c' is the underlying container. Maintainers wondering why 
* this isn't uglified as per style guidelines should note that 
* this name is specified in the standard, [23.2.3.1]. (Why? 
* Presumably for the same reason that it's protected instead 
* of private: to allow derivation. But none of the other 
* containers allow for derivation. Odd.) 
*/ 
_Sequence c; 
संबंधित मुद्दे