2016-05-15 11 views
8

के साथ इंटरफ़ेस मैं सी ++ के लिए जावा-संग्रह-जैसे वातावरण को लागू करने में रूचि रखता हूं। मुझे पता है कि यह एक अच्छा विचार नहीं है और इसी तरह, लेकिन मैं वास्तव में बाद में इसका उपयोग नहीं करना चाहता, लेकिन बस कुछ उन्नत ओओपी कैसे करें सीखें।टेम्पलेट सदस्य फ़ंक्शन

मेरी समस्या है कि मैं पूरी तरह वर्चुअल फ़ंक्शंस के साथ बेस क्लास टेम्पलेट collection<T> चाहता हूं। इनमें से एक कार्य map() होना चाहिए जो std::function<R(T)> लेता है। चूंकि map() आभासी होना चाहिए, मुझे नहीं पता कि किस रिटर्न प्रकार के लिए मुझे इसका उपयोग करना चाहिए। collection<R> संभव नहीं है क्योंकि सदस्य फ़ंक्शन टेम्पलेट वर्चुअल नहीं हो सकते हैं।

मैं अपने collection<T> इंटरफ़ेस के लिए map() सदस्य फ़ंक्शन कैसे जोड़ सकता हूं?

+0

सी ++ मानक कंटेनर के साथ क्या गलत है? –

+2

@ πάντα ῥεῖ ओपी मुझे लगता है कि सीखने के उद्देश्यों के लिए ऐसा करने की कोशिश कर रहा है। –

+0

कुछ भी नहीं, मैं सिर्फ यह जानना चाहता हूं कि शिक्षित उद्देश्य – Exagon

उत्तर

7

मैं अपने collection<T> इंटरफ़ेस के लिए map सदस्य फ़ंक्शन कैसे जोड़ सकता हूं?

संक्षिप्त उत्तर है: आप नहीं करते हैं। अगर मेरे पास collection<int> है और मैं mapstd::to_string पर चाहता हूं, तो मुझे collection<std::string> का उत्पादन करना होगा। लेकिन vector_collection<int> को vector_collection<std::string> और list_collection<int> को list_collection<std::string> बनाने की आवश्यकता है - ताकि परिवर्तन प्रकार को virtual ized होना चाहिए। लेकिन आपके पास virtual सदस्य फ़ंक्शन टेम्पलेट्स नहीं हो सकते हैं, इसलिए इसे व्यक्त करने का कोई तरीका नहीं है।

इस काम के लिए, आपको अपने कंटेनर में रखे गए सभी ऑब्जेक्ट्स के लिए एक सामान्य आधार प्रकार होना चाहिए और फिर केवल एक सामान्य मुखौटा होना चाहिए जिसे आप बीच में डाल सकते हैं। यही है, आप वास्तव में केवल collection<unique_ptr<Object>> है जहां map आपको एक अलग collection<unique_ptr<Object>> देता है, और आप map अपने collection_facade<int, collection<unique_ptr<Object>>> को collection_facade<std::string, collection<unique_ptr<Object>>> में डालते हैं। प्रदर्शन और प्रकार की सुरक्षा के लिए बहुत सारे काम और पूरी तरह से उपेक्षा के साथ, आप वहां जा सकते हैं।


यह टेम्पलेट का लाभ है। अगर मैं vector की तरह कुछ के लिए map लिखना चाहते हैं, मैं सिर्फ इतना है कि लिख सकते हैं:

template <class T, class A, class F, class R = std::result_of_t<F(T)>> 
std::vector<R, A> map(std::vector<T, A> const& v, F f) { 
    std::vector<R, A> mapped; 
    mapped.reserve(v.size()); 
    for (T const& elem : v) { 
     mapped.push_back(f(elem)); 
    } 
    return mapped; 
} 

या:

template <class T, class A, class F, class R = std::result_of_t<F(T)>> 
std::vector<R, A> map(std::vector<T, A> const& v, F f) { 
    return std::vector<R, A>(
     boost::make_transform_iterator(v.begin(), f), 
     boost::make_transform_iterator(v.end(), f) 
     ); 
} 

मैं प्रत्येक कंटेनर के लिए map() अलग से लागू करने के लिए है - लेकिन मैं ऐसा करने के लिए होगा वैसे भी। और अब मैं कुछ भी नहीं दे रहा हूँ। इसके अलावा, आप कितनी बार एल्गोरिदम लिख रहे हैं जो रनटाइम-कंटेनर-अज्ञेयवादी हैं?

+0

और 'आवंटक' भी रिबाउंड किया जा सकता है। – Jarod42

0

बाहरी टेम्पलेट फ़ंक्शन के रूप में map लागू करें। उदाहरण के लिए, आप दो चरणों, आंतरिक आभासी निर्माता और बाहरी टेम्पलेट उपभोक्ता में map विघटित कर सकते हैं।

template<typename T> struct Collection { 
    // virtual T next(); // Java way 
    // C++ way 
    // In simplest cases you can rely on iterator pairs. 
    struct const_iterator { 
     T const &operator*() const; 
     const_iterator &operator++(); 
    } 
    virtual const_iterator begin() const; 
    virtual const_iterator end() const; 
}; 
template<typename R, typename T> Collection<R> map(
    Collection<T> const &coll, std::function<R(T)> const &f); 

अनिवार्य रूप से जटिल कंटेनर और monadic रचनाओं तुम भी begin() और end() अस्वीकार कर सकते हैं को लागू करने और एक स्पष्ट (आंशिक) टेम्पलेट विशेषज्ञता लिखने के लिए।

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