2011-10-06 13 views
5

मैं वर्तमान में टेम्पलेट किए गए कार्यों के साथ कुछ अभ्यास कर रहा हूं। मेरे पास ट्रांसफॉर्म एल्गोरिदम के कार्यान्वयन को लिखने का कार्य था। मैं तो वह ऐसा किया था और यह काम करता है:लैम्ब्डा

template <class in, class out, class T> 
out stransform(in b, in e, out d, T p(const T&)) { 
    while (b != e) 
     *d++ = p(*b++); 
    return d; 
} 

सामान्य की तरह ही बदलना मैं अब

stransform(begin(vec1), end(vec1), back_inserter(vec2), predi<double>); 

की तरह एक स्पष्ट प्रकार के साथ विधेय कॉल करने के लिए है, मैं सी पर ठोकर खाई ++ 11 lambdas और इस तरह मेरी समारोह कॉल करने के लिए चाहता था:

stransform(begin(vec1), end(vec1), back_inserter(vec2), [] (double x) ->double {return x * 10;}); 
मैं एक संकलक त्रुटि है कि प्रकार निष्कर्ष निकाला नहीं जा सकता मिलता है कि के साथ

। यह वह चीज है जिसे मैं समझ नहीं पा रहा हूं क्योंकि मैं वास्तव में दो बार अपने लैम्ब्डा में टी प्रकार को परिभाषित कर रहा हूं।

मैंने मूल ट्रांसफॉर्म फ़ंक्शन को भी वापस देखा, जिसके साथ यह काम कर रहा है। इसके बाद मैंने उसमें से implementation की जांच की और यह पूरी तरह से पूरे फ़ंक्शन के लिए टेम्पलेट क्लास के साथ कार्यान्वित किया गया है। क्या कार्यान्वयन के लिए सही तरीका टेम्पलेट्स के साथ भविष्यवाणी करता है?

template <class in, class out, class UnaryPredicate> 
out stransform(in b, in e, out d, UnaryPredicate p); 

यह कार्य करने के लिए संकेत दिए गए, lambdas और समारोह वस्तुओं को स्वीकार करेंगे:

उत्तर

13

विधेय सामान्यत: एक सरल टेम्पलेट तर्क है।

+0

मैंने ट्रांसफॉर्म के कार्यान्वयन को पढ़ने के बाद ऐसा सोचा, जिससे यह बहुत आसान हो जाता है। मुझे अभी भी आश्चर्य है कि मैं दूसरे मामले में क्यों काम नहीं करता हूं। – inf

+5

@ बांसबोन मुझे लगता है क्योंकि एक लैम्ब्डा कोई फ़ंक्शन नहीं है बल्कि एक फ़ंक्शन ऑब्जेक्ट है, क्योंकि यह राज्य भी पकड़ सकता है (यह एक बंद है और न केवल एक फ़ंक्शन है)। –

+1

ध्यान दें कि एक लैम्ब्डा जो किसी भी कैप्चरिंग नहीं करता है वह सामान्य कार्य (सूचक) में परिवर्तनीय है। – spraff

2

T p(const T&) एक ऐसे कार्य का प्रकार है जो संदर्भ द्वारा लेता है। आपका लैम्ब्डा मूल्य द्वारा अपना तर्क लेता है।

stransform (
    begin (vec1), 
    end (vec1), 
    back_inserter (vec2), 
    [] (const double & x) -> double { 
     return x * 10; 
    }); 

यह काम करना चाहिए। एक लैम्ब्डा जो किसी भी कैप्चरिंग नहीं करता है वह सामान्य कार्य में परिवर्तनीय है।

+1

लेकिन फ़ंक्शन पॉइंटर पर अनावश्यक रूपांतरण पर भरोसा क्यों करें, जब आप केवल मज़दूरों के साथ-साथ फ़ंक्शन पॉइंटर्स के साथ काम करने के लिए फ़ंक्शन को फिर से परिभाषित कर सकते हैं? – jalf

+0

मेरे लिए काम नहीं करता है (msvc2011 का उपयोग करके), या तो। – inf

+0

@jalf फ़ैक्टर को फिर से परिभाषित करना एक बेहतर समाधान है, मैं सहमत हूं। यदि यह समस्या अपरिवर्तनीय लाइब्रेरी कोड के साथ उभरी तो रूपांतरण काम कर सकता है। – spraff

2

यह स्पष्ट रूप से पूरे समारोह

उचित शब्दावली के लिए थोड़ा सा एक तरफ के लिए एक टेम्पलेट वर्ग के साथ लागू किया गया है: std::transform एक समारोह टेम्पलेट, नहीं एक समारोह है। इससे भी महत्वपूर्ण बात, शैली

template<class InputIterator, class OutputIterator, class Functor> 
OutputIterator 
transform(InputIterator begin, InputIterator end, OutputIterator out, Functor f); 

टेम्पलेट पैरामीटर InputIterator, OutputIterator और Functor की घोषणा में वर्ग प्रकार होने की आवश्यकता नहीं है। इस उदाहरण पर विचार:

// function declaration 
int increment(int); 

int array[] = { 0, 1, 2, 3, 4 }; 
transform(std::begin(array), std::end(array), std::begin(array), increment); 

फिर InputIterator और OutputIteratorजिनमें से कोई भी एक वर्ग प्रकार है, होना करने के लिए int* और Functorint(*)(int) है निष्कर्ष निकाला जाता है - बहुत कम एक टेम्पलेट वर्ग है, लेकिन मैं पीछे हटना। और वास्तव में, transform बस के रूप में अच्छी तरह से

template<typename InputIterator, typename OutputIterator, typename Functor> 
OutputIterator 
transform(InputIterator begin, InputIterator end, OutputIterator out, Functor f); 

जहां कीवर्ड typename थोड़ा अधिक टेम्प्लेट पैरामीटर की प्रकृति पर स्पष्ट है घोषित किया जा सकता है: वे किसी भी प्रकार के, प्रकार कर रहे हैं।

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