2011-01-27 15 views
5

मैं चार एल्गोरिदम लागू कर रहा हूं जो पूरी तरह से समान डेटा संरचना का उपयोग करने के अलावा समान हैं - दो priority_queue का उपयोग करते हैं, एक stack का उपयोग करता है, और अंतिम उपयोग queue का उपयोग करता है। वे अपेक्षाकृत लंबे हैं, तो मैं सिर्फ एक समारोह टेम्पलेट है कि एक टेम्पलेट तर्क के रूप में कंटेनर प्रकार स्वीकार करता है करना चाहते हैं और उसके बाद तो जैसे हर एल्गोरिथ्म कॉल कि उचित तर्क के साथ टेम्पलेट है,:मैं एक फ़ंक्शन टेम्पलेट कैसे लिख सकता हूं जो या तो स्टैक या कतार स्वीकार कर सकता है?

template <class Container> 
void foo(/* args */) 
{ 
    Container dataStructure; 
    // Algorithm goes here 
} 

void queueBased(/* args */) 
{ 
    foo<queue<Item> >(/* args */); 
} 

void stackBased(/* args */) 
{ 
    foo<stack<Item> >(/* args */); 
} 

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

इसे पूरा करने का सबसे अच्छा तरीका क्या है? मेरा पहला वृत्ति कतार के लिए एक रैपर वर्ग बनाना था जो top() ऑपरेशन stack के बराबर है, लेकिन मैं पढ़ रहा हूं कि एसटीएल कक्षाएं उप-वर्ग है। मुझे यह व्यवहार कैसे प्राप्त करना चाहिए?

उत्तर

7

आप एक गैर सदस्य top समारोह कंटेनर एडाप्टर के प्रकार पर अतिभारित लिख सकते हैं:

template <typename T> 
T& top(std::stack<T>& s) { return s.top(); } 

template <typename T> 
T& top(std::queue<T>& q) { return q.front(); } 

// etc. 

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

यह अनुक्रम कंटेनर का उपयोग करने के लिए और अधिक सरल हो सकता है (उदा।std::vector) अनुक्रम एडाप्टर में से किसी एक का उपयोग करने के बजाय सीधे।

+1

मैं खोज एल्गोरिदम का एक सेट कार्यान्वित कर रहा हूं, इसलिए मुझे एडाप्टर के विशिष्ट क्रमिक व्यवहार की आवश्यकता है। (एलआईएफओ मुझे एक चौड़ाई पहली खोज देता है जबकि फीफो मुझे गहराई देता है, उदाहरण के लिए) –

-1

front() और top() कुछ प्रकार के कंटेनरों के लिए विशिष्ट हैं, लेकिन सभी एसटीएल कंटेनर *begin() का समर्थन करते हैं।

+2

'std :: priority_queue',' std :: stack', और 'std :: queue' कंटेनर नहीं हैं और उनमें से कोई भी कर रहे हैं पुनरावृत्त अनुक्रम। –

0

queue, priority_queue और stack सभी कंटेनर एडाप्टर हैं; वे एक अंतर्निहित कंटेनर के चारों ओर रैपर हैं (डिफ़ॉल्ट रूप से dequequeue और stack और vectorpriority_queue के लिए)।

vector, deque और list ("असली" कंटेनर वर्ग) अपने तरीके से ज्यादातर हिस्सा के बाद से, आप बीच आदमी में कटौती और इसके बजाय उन वर्गों इस्तेमाल कर सकते हैं।

और ध्यान रखें कि सार्वजनिक विरासत एसटीएल कंटेनरों के लिए एक अच्छा विचार नहीं है; निजी विरासत ठीक है (और शायद आप जो चाहते हैं)।

1

आप विरासत का उपयोग किये बिना std::queue के आसपास एक रैपर बना सकते हैं; वास्तव में, विरासत क्योंकि आप एक queue बल्कि से शोधन या विस्तारqueue सजाने की कोशिश कर रहे यहां गलत उपकरण होगा। यहां एक संभावित कार्यान्वयन है:

template <typename QueueType> 
class QueueWrapper { 
public: 
    explicit QueueWrapper(const QueueType& q) : queue(q) { 
     // Handled in initializer list 
    } 

    typedef typename QueueType::value_type value_type; 

    value_type& top() { 
     return queue.front(); 
    } 
    const value_type& top() const { 
     return queue.front(); 
    } 

    void pop() { 
     queue.pop(); 
    } 
private: 
    QueueType queue; 
}; 

आशा है कि इससे मदद मिलती है!

2

आप सही विधि का चयन करने के लिए आंशिक विशेषज्ञता का उपयोग कर सकते हैं:

template<class Container> 
struct foo_detail { 
    static typename Container::value_type& top(Container &c) { return c.top(); } 
    static typename Container::value_type const& top(Container const &c) { return c.top(); } 
}; 
template<class T, class Underlying> 
struct foo_detail<std::queue<T, Underlying> > { 
    typedef std::queue<T, Underlying> Container; 
    static typename Container::value_type& top(Container &c) { return c.front(); } 
    static typename Container::value_type const& top(Container const &c) { return c.front(); } 
}; 

template<class Container> 
void foo(/* args */) 
{ 
    Container dataStructure; 
    // Use foo_detail<Container>::top(dataStructure) instead of dataStructure.top(). 
    // Yes, I know it's ugly. :(
} 
संबंधित मुद्दे

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