2011-03-11 10 views
22

मैं यहाँ Printing 1 to 1000 without loop or conditionalsसंकलन समय रिकर्सन कैसे काम करता है?

कोई कोड मिलता कृपया कोई व्याख्या कर सकते हैं कि कैसे संकलन समय प्रत्यावर्तन काम करता है, यह गूगल

// compile time recursion 
template<int N> void f1() 
{ 
    f1<N-1>(); 
    cout << N << '\n'; 
} 

template<> void f1<1>() 
{ 
    cout << 1 << '\n'; 
} 


int main() 
{ 
    f1<1000>(); 
} 

में नहीं पा सके धन्यवाद!

+0

असल में एक चाल है, विशेषज्ञता एक सशर्त है, हालांकि कोई 'if' कीवर्ड नहीं है ... –

+0

क्या रन टाइम रिकर्सन की तुलना में अंगूठे का नियम बहुत तेज है? –

+0

नियमित पुनरावृत्ति के स्थान पर इसका उपयोग करने का क्या फायदा है? – zzzzz

उत्तर

11

यह बार-बार N (f1<N>() कॉल f1<N-1> और इसी तरह) के लिए कम हो रही मूल्यों के साथ f1<N> टेम्पलेट को दर्शाता है। N==1 के लिए स्पष्ट विशेषज्ञता रिकर्सन समाप्त होती है: जैसे ही N 1 हो जाता है, संकलक टेम्पलेट वाले के बजाय विशेष फ़ंक्शन चुनता है।

f1<1000>() संकलक को f1<N> 999 बार तत्काल करने का कारण बनता है (अंतिम कॉल में f1<1> पर गिनती नहीं)। यही कारण है कि कोड को संकलित करने में कुछ समय लग सकता है जो टेम्पलेट मेटा-प्रोग्रामिंग तकनीकों का भारी उपयोग करता है।

पूरी बात कंपाइलर के अनुकूलन कौशल पर भारी निर्भर करती है - आदर्श रूप से, इसे रिकर्सन को हटा देना चाहिए (जो केवल for लूप का उपयोग करके लूप को अनुकरण करने के लिए हैक के रूप में कार्य करता है)।

2

यह अवधारणात्मक रूप से लगभग उसी तरह चलता है जैसे रनटाइम रिकर्सन। f1<1000>f1<999> पर कॉल करता है और फिर 1000 प्रिंट करता है। f1<999>f1<998> पर कॉल करता है और फिर 999 प्रिंट करता है। एक बार यह 1 हो जाता है जब टेम्पलेट विशेषज्ञता रिकॉर्ज़ेशन को रद्द करने के लिए बेस केस के रूप में कार्य करती है।

+0

यह 0 से 1000 तक क्यों प्रिंट करता है और 1000 से 0 तक नहीं? – VextoR

+1

@VextoR: ऐसा इसलिए है क्योंकि यह पहले f1 पर कॉल करता है, फिर प्रिंट करता है। – sharptooth

+1

@VextoR क्योंकि यह अगले टेम्पलेट को तुरंत चालू करने के बाद कंसोल में 'एन' आउटपुट कर रहा है। – Maxpm

1

सरल पर्याप्त, प्रत्येक टेम्पलेट instanciation बदले पैरामीटर के साथ एक नया समारोह बनाते हैं। जैसा कि आपने परिभाषित किया है: f1_1000(), f1_999() और इसी तरह।

प्रत्येक फ़ंक्शन फ़ंक्शन को इसके नाम पर 1 कम के साथ कॉल करता है। चूंकि f1_1() को परिभाषित करने के लिए एक अलग टेम्पलेट है, रिकर्सिव नहीं है, हमारे पास एक स्टॉप केस भी है।

1

यह शुद्ध संकलन-समय रिकर्सन होने की गारंटी नहीं है। कंपाइलर को सभी पैरामीटर मान 2 से 1000 के लिए फ़ंक्शन f1() को तुरंत चालू करना होगा और वे एक-दूसरे को कॉल करेंगे।

फिर संकलक देख सकता है कि उन कॉल को cout << ... कथन के अनुक्रम में बदल दिया जा सकता है। शायद यह कॉल को समाप्त करता है, शायद नहीं - यह संकलक पर निर्भर है। सी ++ के बिंदु से यह फ़ंक्शन कॉल की एक श्रृंखला है और संकलक तब तक कर सकता है जब तक यह व्यवहार में बदलाव नहीं करता है।

1

आपके पास फैक्ट्रोरियल गणना here समझाई गई है।

बीटीडब्ल्यू यह नोट करता है कि आपका कार्य नकारात्मक संख्याओं के लिए काम नहीं करता है।