2010-01-17 15 views
5

मेरा मतलब है कि निम्नलिखित है। मैं एक टेम्पलेट फ़ंक्शन चाहता हूं जो दो वेक्टर इटरेटर्स (या दो पॉइंटर्स को डबल की सरणी में लेता है) लेता है और एक डबल देता है जो किसी भी तरह से वेक्टर इटरेटर्स या सरणी पॉइंटर्स से संबंधित होता है जो मैं पास करता हूं। हालांकि, मैं इसे डबल या int, या किसी अंकगणितीय प्रकार के लिए काम करना चाहता हूं।एक सी ++ टेम्पलेट फ़ंक्शन में क्या मैं एक डिफ्रेंस किए गए तर्क प्रकार को वापस कर सकता हूं?

मुझे लगता है कि मैं कहता हूँ की अनुमति नहीं कर रहा हूँ:

template <class T> 
T* func(T Begin, T End) 

T new_variable = Begin + 5; 

return (*new_variable); 
} 

क्योंकि संकलक नहीं समझोगे क्या टी * साधन। एक समाधान जिसे मैंने सोचा था, वह है जो मैं वापस करने की कोशिश कर रहा हूं और इसे तीसरा तर्क देता हूं:

template <class T> 
void func(T Begin, T End, T* new_variable) 

new_variable = Begin + 5; 

return (*new_variable); 
} 

क्या यह काम करेगा? यहां तक ​​कि अगर ऐसा करने का एक और तरीका है जो मैं करने की कोशिश कर रहा हूं? (क्षमा करें यदि मैं नहीं स्पष्ट पर्याप्त किया गया है।)

+3

ध्यान दें कि कंपाइलर टेम्पलेट फ़ंक्शन के रिटर्न प्रकार में 'T *' को समझता है; समस्या यह है कि '* new_variable' का प्रकार' टी * 'नहीं है। – outis

उत्तर

10

आप एक डबल वापस जाने के लिए चाहते हैं (यानी प्रकार है कि आप जब अपसंदर्भन मिलेगा), तो आपको इटरेटर लक्षण का उपयोग कर सकते हैं:

template<typename RandomAccessIterator> 
typename std::iterator_traits<RandomAccessIterator>::value_type 
func(RandomAccessIterator a, RandomAccessIterator b) { 
    typedef typename std::iterator_traits<RandomAccessIterator>::value_type 
     value_type; 

    // use value_type now, when you want to save some temporary 
    // value into a local variable, for instance 
    value_type t = value_type(); 
    for(; a != b; ++a) t += *a; 
    return t; 
} 

इन पॉइंटर्स समेत सभी इटरेटर के लिए काम:

int main() { 
    int d[3] = { 1, 2, 3 }; 
    assert(func(d, d + 3) == 6); 
} 
+0

यह वही लगता है जो मुझे चाहिए! कुछ बिंदु, हालांकि: 1) मुझे लगता है कि आप लूप के लिए initalize भूल गए हैं। 2) क्या यह ठीक है जब आप टाइपपीफ का उपयोग किसी नए प्रकार के नाम पर करने के लिए करते हैं, इसे value_type कहते हैं? क्या यह आरक्षित कीवर्ड या कुछ नहीं है? 3) मुझे iterator_traits के बारे में पता नहीं था क्योंकि मैं त्वरित सी ++ पढ़ रहा हूं। क्या मैं जोसुटिस की किताब में इसके बारे में अधिक जानकारी प्राप्त कर सकता हूं? – jackj

+2

@jackj 1) यदि आपको इसकी आवश्यकता नहीं है तो आप फॉर-लूप प्रारंभिक अनुभाग को छोड़ सकते हैं। "टी" पूरी तरह से value_type (int के लिए 0) के डिफ़ॉल्ट मान में प्रारंभ किया गया है, 2) हां, value_type आरक्षित नहीं है। हम इसे लंबे प्रकार के नाम को छोटा करने के लिए उपयोग कर सकते हैं। 3) हां जोसुटिस की किताब को कवर करना चाहिए। :) –

+0

वाह! यह स्टैक ओवरफ्लो पर मेरा पहला समय है, लेकिन मुझे पता है कि मैं वापस आऊंगा। तुम लड़के गजब हो! बहुत बहुत धन्यवाद। – jackj

3

ठीक है, आपका कोड टेक्स्ट में वर्णित वर्णन के विपरीत लगता है। यदि T इटेटरेटर प्रकार है, तो इटेटर डीरेंस (जैसा कि आपने पाठ में कहा था) का परिणाम टाइप T * (जैसा कि आप कोड में विश्वास करते हैं) है। T * एक पूरी तरह से विपरीत बात है: अगर आप पता अपने इटरेटर के बारे में बताते हैं, तो यह कुछ ऐसा है जो आपको अस्वीकार नहीं किया गया है।

वास्तव में, वहाँ "dereferenced प्रकार" सी ++ कोर भाषा सुविधाओं का उपयोग कर व्यक्त करने के लिए कोई रास्ता नहीं है (शायद decltype भविष्य में यह करना होगा, decltype(*T()) के रूप में)। प्रकार T के पूर्ववर्तन के परिणाम का वर्णन करने का एकमात्र तरीका लाइब्रेरी-आधारित समाधान का उपयोग करना है: इटेटरेटर लक्षण, जैसा कि जोहान्स ने अपने उत्तर में समझाया।

+0

धन्यवाद आउटिस और एंड्रीटी। आप सही हैं, कोड जो मैंने सोचा था, उसके विपरीत है। मुझे लगता है कि मुझे इस तथ्य से भ्रमित हो गया है कि सी ++ में यूनरी * का उपयोग पॉइंटर घोषित करने के लिए किया जाता है, और एक पॉइंटर या इटरेटर को कम करने के लिए भी किया जाता है, लेकिन ये दो चीजें अलग होती हैं। – jackj

+1

@jackj: ऐसा इसलिए है क्योंकि आपको घोषणा 'टी * आईडी' को "आईडी 'प्रकार के रूप में' टी '' के रूप में पढ़ना है: दुर्भाग्यवश दुर्भाग्यवश 'टी * ए, बी;' जैसी बग की ओर जाता है, जो परिभाषित करता है एक 'टी *' और 'टी'।यही कारण है कि यह 'टी आईडी [एन]' 'टी [एन] आईडी' नहीं है: क्योंकि' id [n] '' t' का प्रकार है। –

+1

@jackj: यदि आपको प्रकार की घोषणाओं में समस्याएं आ रही हैं, तो http://unixwiz.net/techtips/reading-cdecl.html या http://www.ericgiguere.com/articles/reading-c-declarations पढ़ने का प्रयास करें। एचटीएमएल। मैंने देखा है कि सबसे सरल वर्णन (और वाक्यविन्यास का कारण) http://cm.bell-labs.com/cm/cs/who/dmr/chist.html से आता है: घोषणा कीजिए कि अभिव्यक्ति एक अभिव्यक्ति है जिसका मूल्य है घोषणा की शुरुआत में नामित प्रकार (उदाहरण के लिए 'टी (* डी) [2]' के लिए, '(* डी) [1]' के बारे में सोचें 'टी' होने के नाते)। – outis

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

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