2010-04-25 17 views
5

नीचे दिए गए कोड के संबंध में, कंपाइलर किस टेम्पलेट फ़ंक्शन को कॉल करने का विकल्प चुनता है? यदि कॉन्स टी & फ़ंक्शन छोड़ा गया है, तो टी & फ़ंक्शन हमेशा कॉल किया जाता है। यदि टी & फ़ंक्शन छोड़ा गया है, तो कॉन्स टी & फ़ंक्शन हमेशा कॉल किया जाता है। यदि दोनों शामिल हैं, तो परिणाम नीचे दिए गए हैं।संकलन कैसे कॉल करता है कि कौन सा टेम्पलेट फ़ंक्शन कॉल करना है?

#include <iostream> 
#include <typeinfo> 

template <typename T> 
void function(const T &t) 
{ 
    std::cout << "function<" << typeid(T).name() << ">(const T&) called with t = " << t << std::endl; 
} 

template <typename T> 
void function(T &t) 
{ 
    std::cout << "function<" << typeid(T).name() << ">(T&) called with t = " << t << std::endl; 
} 

int main() 
{ 
    int i1 = 57; 
    const int i2 = -6; 

    int *pi1 = &i1; 
    int *const pi3 = &i1; 
    const int *pi2 = &i2; 
    const int *const pi4 = &i2; 

    function(pi1); ///just a normal pointer -> T& 
    function(pi2); ///cannot change what we point to -> T& 
    function(pi3); ///cannot change where we point -> const T& 
    function(pi4); ///cannot change everything -> const T& 

    return 0; 
} 

/* g++ output: 
function<Pi>(T&) called with t = 0x22cd24 
function<PKi>(T&) called with t = 0x22cd20 
function<Pi>(const T&) called with t = 0x22cd24 
function<PKi>(const T&) called with t = 0x22cd20 
*/ 

/* bcc32 output: 
function<int *>(T&) called with t = 0012FF50 
function<const int *>(T&) called with t = 0012FF4C 
function<int *>(const T&) called with t = 0012FF50 
function<const int *>(const T&) called with t = 0012FF4C 
*/ 

/* cl output: 
function<int *>(T&) called with t = 0012FF34 
function<int const *>(T&) called with t = 0012FF28 
function<int *>(const T&) called with t = 0012FF34 
function<int const *>(const T&) called with t = 0012FF28 
*/ 
+0

एक छोटी सी चाल है, जब आप जी का उपयोग कर ++ होने के लिए होने की स्पष्ट रूप से निरंतर सूचक। '__PRETTY_FUNCTION__' आपके फ़ंक्शन का वर्णन करने वाली एक अच्छी तरह से स्वरूपित स्ट्रिंग प्रदान करता है, जिसमें" पीआई "के बजाय टेम्पलेट पैरामीटर प्रकार [" int * "शामिल हैं)। जब यह टेम्पलेट्स काम करता है, तो सीखने के दौरान मुझे यह अमूल्य लगता है, क्योंकि 'टाइपिड (टी) .name()' के लिए डिफ़ॉल्ट व्यवहार g ++ के तहत डिफ़ॉल्ट क्रिप्टिक है। मेरा मानना ​​है कि '__FUNCSIG__' वीएस के तहत समान कार्यक्षमता प्रदान करता है, लेकिन मुझे इसकी पुष्टि करने के लिए इसका उपयोग नहीं है। –

उत्तर

3

Here संकलक माध्यम से चला जाता प्रक्रिया का एक संक्षिप्त सारांश है। इसमें सबकुछ शामिल नहीं है, लेकिन यह आपको शुरू कर देता है।

इस मामले में, निर्णय गैर-टेम्पलेटेड फ़ंक्शन के समान ही बनाया जाता है। void f(int&) और void f(const int&) दिया गया, पहला नियमित इनट्स के लिए चुना जाएगा, और दूसरा कॉन्स इंक के लिए चुना जाएगा। पैरामीटर आसानी से इनपुट को इस तरह से मेल खाते हैं: यदि आप एक चर प्रदान करते हैं तो आप संशोधित कर सकते हैं, यह एक फ़ंक्शन को कॉल करता है जो उन्हें संशोधित कर सकता है, यदि आप एक वेरिएबल प्रदान करते हैं जिसे आप संशोधित नहीं कर सकते हैं, तो यह एक ऐसा फ़ंक्शन कॉल करता है जो उन्हें संशोधित नहीं कर सकता है।

अपने नमूना कोड में, pi2, const int * के रूप में घोषित किया जा रहा है, निरंतर डेटा के लिए एक गैर-स्थिर सूचक है। तो अपने फ़ंक्शन के भीतर, आप t बदल सकते हैं, लेकिन *t नहीं। इसके विपरीत, pi3 गैर-निरंतर डेटा के लिए एक स्थिर सूचक है। तो आप *t बदल सकते हैं लेकिन t नहीं बदल सकते हैं।

यदि आप थोड़ा अपने कोड बदल दिया है:

function(*pi1); 
function(*p12); 
function(*pi3); 
function(*pi4); 

इस मामले में, पहली और तीसरी दोनों T& संस्करण के लिए हल है, क्योंकि *pi1 और *pi3 प्रकार int& के दोनों होते हैं और इसलिए संशोधित किया जा सकता। *pi2 और *pi4 दोनों const int& दोनों हैं, इसलिए वे const T& अधिभार को हल करते हैं।

0

यह है कि चर स्थिर है या नहीं: पहला वाला स्थिर नहीं है। दूसरा अंक कुछ स्थिर होता है, लेकिन हम इसे कहां बदल सकते हैं, तीसरे और चौथे दोनों में निरंतर सूचक होता है, जिसका मतलब है कि वेरिएबल स्वयं ही है, हम जहां भी इंगित करते हैं, हम उसे बदल नहीं सकते हैं।

typedef const int Cint; 
Cint * int1; 

स्पष्ट रूप से निरंतर int के लिए सूचक।

typedef int * Pint 
const Pint int2 

गैर निरंतर पूर्णांक

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