2012-12-02 9 views
7

Function passed as template argument के बारे में, समुदाय विकी बेन Supnik द्वारा प्रदान की जवाब इनलाइन करने instantiated समारोह टेम्पलेट्स के मुद्दे पर चर्चा करता है।क्यों यह स्पष्ट एक टेम्पलेट समारोह इन्स्टेन्शियशन inlined है कि नहीं किया जाएगा?

स्पष्ट रूप से इस:

template<typename OP> 
int do_op(int a, int b, OP op) 
{ 
    return op(a,b,); 
} 

int add(int a, b) { return a + b; } 

int (* func_ptr)(int, int) = add; 

int c = do_op(4,5,func_ptr); 

जवाब यह कहना (अंतिम पंक्ति है, जो समारोह टेम्पलेट do_op को दर्शाता है के संबंध में) पर चला जाता है:

कि जवाब में निम्नलिखित कोड है inlined हो रही नहीं है।

मेरा प्रश्न यह है: यह स्पष्ट क्यों है कि यह रेखांकित नहीं हो रहा है?

उत्तर

5

वह क्या कह रहा है (मुझे लगता है) यह है कि add फ़ंक्शन इनलाइन नहीं हो रहा है। दूसरे शब्दों में, संकलक do_op इस तरह इनलाइन सकता है:

int c = func_ptr(4, 5); 

लेकिन यह भी add इस तरह अनुरूप नहीं होगा:

int c = 4 + 5; 

हालांकि, वह यह है कि सरल उदाहरण में गलत हो सकता है।

आम तौर पर, जब आप किसी सूचक के माध्यम से फ़ंक्शन को कॉल करते हैं, तो संकलक (संकलन-समय पर) नहीं जानता कि आप किस फ़ंक्शन को कॉल करेंगे, इसलिए यह फ़ंक्शन को इनलाइन नहीं कर सकता है। उदाहरण:

void f1() { ... } 
void f2() { ... } 

void callThroughPointer() { 
    int i = arc4random_uniform(2); 
    void (*f)() = i ? f2 : f1; 
    f(); 
} 

यहाँ, संकलक पता नहीं कर सकते हैं कि callThroughPointerf1 या f2 फोन करेगा, इसलिए यह इनलाइन करने के लिए या तो f1 या callThroughPointer में f2 के लिए कोई रास्ता नहीं है।

हालांकि, अगर संकलक संकलन समय क्या फ़ंक्शन कॉल किया जाएगा पर साबित कर सकते हैं, यह समारोह इनलाइन करने के लिए अनुमति दी है। उदाहरण:

void f1() { ... } 
void f2() { ... } 

void callThroughPointer2() { 
    int i = arc4random_uniform(2); 
    void (*f)() = i ? f2 : f1; 
    f = f1; 
    f(); 
} 

यहाँ, संकलक साबित कर सकते हैं कि f हमेशा f1 हो जाएगा, तो यह callThroughPointer2 में f1 इनलाइन करने की अनुमति दी है। (यह मतलब नहीं है यह होगा इनलाइन f1 ...)

इसी तरह, उदाहरण आप अपनी पोस्ट में उद्धृत में, संकलक साबित कर सकते हैं कि func_ptrdo_op करने के लिए कॉल में हमेशा add है, इसलिए यह add इनलाइन करने की अनुमति दी है । (यह मतलब नहीं है यह होगा इनलाइन add ...)

0

क्यों यह स्पष्ट है कि इस inlined नहीं हो रही है?

यह नहीं है। कोई कारण नहीं संकलक कि स्निपेट में कोड के सभी इनलाइन नहीं कर सकता है।

+1

ऐसा कोई कारण नहीं है कि यह नहीं हो सका, लेकिन इसके कई कारण हैं कि ऐसा करने का प्रयास क्यों नहीं किया जा सकता है। अगर मुझे गलत जानकारी नहीं दी गई है तो सी (और सी ++) कंपाइलर्स ने हाल ही में जब तक इनलाइनिंग के उद्देश्य के लिए फ़ंक्शन पॉइंटर्स को ट्रैक करने का प्रयास नहीं किया था। –

+1

@ कोनराड रुडॉल्फ - निश्चित रूप से, लेकिन दावा यह है कि ** यह स्पष्ट है कि यह रेखांकित नहीं हो रहा है **। यह बिल्कुल स्पष्ट नहीं है। –

3

फ़ंक्शन पॉइंटर के माध्यम से फ़ंक्शन को कॉल करते समय, कंपाइलर फ़ंक्शन पॉइंटर के माध्यम से कॉल से बचने की अत्यधिक संभावना नहीं है।केवल अगर संकलक साबित कर सकता है कि यह जानता है कि फ़ंक्शन पॉइंटर को किस प्रकार प्रारंभ किया जा रहा है और इसे बदला नहीं जा सकता है, तो यह संभवतः फ़ंक्शन पॉइंटर के माध्यम से फ़ंक्शन कॉल से बच सकता है और इस प्रकार, फ़ंक्शन को इनलाइन कर सकता है। उद्धृत सेटअप, जैसे कि, में

int (* func_ptr)(int, int) = add; 

समारोह सूचक func_ptr परिवर्तनीय है और संकलक, इस प्रकार, इसकी गारंटी नहीं है कि यह कभी नहीं बदलेगा। नतीजतन, यह संभावित रूप से कॉल को add पर रेखांकित नहीं कर सकता है।

यदि कोड का स्निपेट वास्तव में पूरा होता है, तो प्रारंभिक समय के दौरान चीजें होती हैं और वास्तव में, कंपाइलर वास्तव में जान सकता है कि func_ptr को add रखने के लिए प्रारंभ किया गया है।

+0

बहुत उपयोगी ... काश मैं स्वीकार्य उत्तर के रूप में कई उत्तरों को चिह्नित कर सकता हूं। –

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