2010-03-04 3 views
5

इनलाइनिंग बनाम टेम्पलेट के साथ metaprogramming इसके लायक सरणी तत्वों कॉपी करने के लिए निम्नलिखित की तरह कोड लिखने के लिए है:सी ++

#include <iostream> 
using namespace std; 


template<int START, int N> 
struct Repeat { 
    static void copy (int * x, int * y) { 
    x[START+N-1] = y[START+N-1]; 
    Repeat<START, N-1>::copy(x,y); 
    } 
}; 

template<int START> 
struct Repeat<START, 0> { 
    static void copy (int * x, int * y) { 
    x[START] = y[START]; 
    } 
}; 



int main() { 


    int a[10]; 
    int b[10]; 

      // initialize 
    for (int i=0; i<=9; i++) { 
    b[i] = 113 + i; 
    a[i] = 0; 
    } 

      // do the copy (starting at 2, 4 elements) 
    Repeat<2,4>::copy(a,b); 

      // show 
    for (int i=0; i<=9; i++) { 
    cout << a[i] << endl; 
    } 

} //() 

या बेहतर एक inlined समारोह का उपयोग करने के लिए है?

पहला दोष यह है कि आप टेम्पलेट में चर का उपयोग नहीं कर सकते हैं।

+2

आपको केवल 'std :: copy' का उपयोग करना चाहिए। आप लगभग निश्चित हो सकते हैं कि * * * कुछ मेटाप्रोग्रामिंग तकनीकों का उपयोग करता है ताकि int arrays के बीच memmove के बीच प्रतिलिपि अग्रेषित किया जा सके। – UncleBens

+1

क्राइस्ट, मैं सी ++ संकलन समय मेटाप्रोग्रामिंग को देखकर अब और समय व्यतीत करने के बजाय 10 जीवनकाल प्रोग्रामिंग प्रोलॉग खर्च करूंगा :(। अगर आपको कुछ कॉपी करना होगा, तो आपको इसकी प्रतिलिपि बनाना होगा, आप सोचकर इसे दूर नहीं कर सकते यह संकलन समय पर सिर्फ इसलिए कि आपको लगता है कि आप उन चरों की पहचान कर सकते हैं जिन्हें कॉपी किया जाएगा –

+0

@ हसन: डेटाटाइप और संरेखण के आधार पर, प्रतिलिपि बनाने के लिए अलग-अलग रणनीतियां उपयुक्त हो सकती हैं, और ऑपरेशन को नाटकीय रूप से गति देना संभव हो सकता है। "सिर्फ एक प्रति" नहीं है। (लेकिन @UncleBens कहते हैं, 'std :: copy' पहले से ही यह करता है) – jalf

उत्तर

8

यह बेहतर नहीं है। सबसे पहले, यह वास्तव में संकलित समय नहीं है, क्योंकि आप यहां फ़ंक्शन कॉल करते हैं। यदि आप भाग्यशाली हैं, तो संकलक इनलाइनों को रेखांकित करेगा और एक लूप के साथ समाप्त होगा जिसे आप स्वयं को बहुत कम मात्रा में लिख सकते हैं (या बस std::copy का उपयोग करके)।

+3

+1 एफ * सीके हाँ! ! – Tom

+2

यह सिर्फ सच नहीं है। रिकर्सन संकलन-समय है, यहां कोई रनटाइम रिकर्सन नहीं है। प्रत्येक कार्य एक अलग वर्ग का होता है, और यह वही कार्य नहीं है। हालांकि जावा के लिए क्या सच होगा! – PierreBdR

+2

@PierreBdr, यह सच है कि प्रत्येक बार एक अलग कार्य शामिल होता है। लेकिन ये रनटाइम पर किए गए फ़ंक्शन कॉल हैं, और प्रभाव यह है कि आप एक ही फ़ंक्शन को एक पुनरावर्ती तरीके से कॉल करेंगे (जैसा कि * सच्चा * संकलन समय रिकर्सन अला 'के विपरीत है' स्थिर int const value = class :: मान + 1 ; ')। केवल अंतर यह है कि संकलन समय पर अंतिम स्थिति का मूल्यांकन किया जा सकता है। लेकिन एक समकक्ष लूप की स्थिति भी हो सकती है। –

0

आपको यह नहीं करना चाहिए। टेम्पलेट्स का आविष्कार अलग-अलग उद्देश्यों के लिए किया गया था, न कि गणना के लिए, हालांकि आप इसे कर सकते हैं। सबसे पहले आप चर का उपयोग नहीं कर सकते हैं, दूसरा टेम्पलेट संकलन पर अप्रयुक्त संरचनाओं का विशाल उत्पादन करेगा, और तीसरा है: for (int i = start; i <= end; i++) b[i] = a[i];

+1

हां, टेम्पलेट्स का आविष्कार अलग-अलग उद्देश्यों के लिए किया गया था, लेकिन आप कल्पना नहीं कर सकते कि कितनी किताबें writte और e-ink उस दूसरे गैर-इरादा उपयोग के लिए उपयोग की जाती हैं! – cibercitizen1

+0

हाँ, टेम्पलेट्स के बारे में दावा न करें जिन्हें आप प्रमाणित नहीं कर सकते हैं। –

1

सामान्य नियम: संकलन समय पर ज्ञात चीज़ों के लिए टेम्पलेट का उपयोग करें, रन टाइम पर ज्ञात चीज़ों के लिए इनलाइनिंग का उपयोग करें। यदि आप संकलन समय पर अपने सरणी के आकार को नहीं जानते हैं, तो इसके लिए टेम्पलेट का उपयोग न करें।

0

यह बेहतर है क्योंकि आप अपने द्वारा अनलॉक करने वाले लूप को नियंत्रित और लागू करते हैं।

एक पाश के अनुकूलन विकल्प के आधार पर संकलक द्वारा unrolled जा सकता है ...

तथ्य यह है कि copy साथ कॉपी करने लगभग है सबसे अच्छा एक अच्छा सामान्य जवाब क्योंकि पाश unrolling किया जा सकता है जो कुछ भी गणना नहीं है अंदर किया गया ...