2010-04-25 13 views
5

Per quanto riguarda il codice sottostante, in che modo il compilatore sceglie quale funzione modello chiamare? Se la funzione const T & viene omessa, viene sempre chiamata la funzione T &. Se la funzione T & viene omessa, viene sempre chiamata la funzione const T &. Se entrambi sono inclusi, i risultati sono i seguenti.In che modo la compilazione sceglie quale funzione modello chiamare?

#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

Un piccolo trucco, quando vi capita di essere utilizzando g ++. '__PRETTY_FUNCTION__' fornisce una stringa ben formattata che descrive la tua funzione, inclusi i tipi di parametri del template [" int * "invece di" Pi "]. Ho trovato questo inestimabile quando ho imparato come funzionano i template, dal momento che il comportamento predefinito per 'typeid (T) .name()' in g ++ è piuttosto criptico. Credo che "__FUNCSIG__' fornisca funzionalità simili sotto VS, ma non ho accesso ad esso per verificare. –

risposta

3

Here è una breve sintesi del processo compilatore passa attraverso. Non copre tutto, ma ti fa iniziare.

In questo caso, la decisione viene eseguita come una funzione non basata su modelli. Dato void f(int&) e void f(const int&), il primo sarà scelto per interi regolari, e il secondo per interi const. I parametri corrispondono semplicemente meglio agli input in questo modo: se si fornisce una variabile che è possibile modificare, chiama una funzione che può modificarli, se si fornisce una variabile che non è possibile modificare, chiama una funzione che non può modificarli.

Nel codice di esempio, pi2, dichiarato come const int *, è un puntatore non costante a dati costanti. Pertanto, all'interno della funzione, è possibile modificare t, ma non *t. Al contrario, pi3 è un puntatore costante a dati non costanti. Quindi puoi cambiare *t ma non t.

Se si modifica il codice di un po ':

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

In questo caso, il primo e il terzo sarebbe sia risolvere alla versione T&, perché *pi1 e *pi3 sono entrambi di tipo int& e può quindi essere modificati. *pi2 e *pi4 sono entrambi const int&, quindi risolvono il sovraccarico di const T&.

0

riguarda se la variabile stessa è costante: il primo non è affatto costante. il secondo punta a qualcosa che è costante, ma potremmo cambiare dove punta, il terzo e il quarto hanno entrambi un puntatore costante, il che significa che la variabile stessa è const, non possiamo cambiare ovunque punti.

typedef const int Cint; 
Cint * int1; 

puntatore ovviamente a costante int.

typedef int * Pint 
const Pint int2 

ovviamente costante puntatore a non costante int

Problemi correlati