2015-05-14 10 views
7

Stavo leggendo Effective Modern C++ di S. Meyers e ho trovato qualcosa che non riesco a capire.Perché il controllo dei tipi all'interno dei modelli è più rigido?

L'articolo 8 spiega perchédeve essere preferito su 0 o NULL. L'argomento principale a favore di nullptr è un comportamento più sicuro nelle risoluzioni di sovraccarico. In pratica si evitano mixaggi imprevisti tra puntatori e tipi interi, ma questo non è il punto della mia domanda.

per arrivare alla mia domanda effettiva, si consideri il codice qui sotto, che si basa su l'esempio utilizzato nel libro:

#include <memory> 

class MyClass { 
    int a; 
}; 

// dummy functions that take pointer types 
int f1(std::shared_ptr<MyClass> spw){return 1;}; 
double f2(std::unique_ptr<MyClass> upw){return 1.0;}; 
bool f3(MyClass* pw){return true;}; 

// template that calls a function with a pointer argument 
template<typename FuncType, 
     typename PtrType> 
auto CallFun(FuncType func, PtrType ptr) -> decltype(func(ptr)) 
{ 
    return func(ptr); 
} 

int main() 
{ 
    // passing null ptr in three different ways 
    // they all work fine int this case 
    auto result1 = f1(0);  // pass 0 as null ptr to f1 
    auto result2 = f2(NULL);  // pass NULL as null ptr to f2 
    auto result3 = f3(nullptr); // pass nullptr as null ptr to f3 } 

    // passing null ptr in three different ways through the template 
    // only nullptr works in this case 
    auto result4 = CallFun(f1, 0);   // compile error! 
    auto result5 = CallFun(f2, NULL);  // compile error! 
    auto result6 = CallFun(f3, nullptr); // OK 

    return 0; 
} 

I primi tre chiamate dirette al f1, f2 e f3 compilare bene per entrambi i 0 , NULL o nullptr come puntatore nullo. Le successive 3 chiamate, che vengono eseguite tramite la funzione template CallFun, sono molto più schizzinose: è necessario utilizzare nullptr oppure non verrà accettata alcuna conversione tra tipi di numeri interi (0 e NULL). In altre parole, il controllo del tipo sembra essere più rigoroso quando si verifica all'interno del modello. Qualcuno può chiarire cosa sta succedendo?

+0

Ho chiesto esattamente la stessa domanda :) Vedere il collegamento dupe che ho inserito e vedere anche le virgolette standard. – vsoftco

risposta

7

CallFun deduce il tipo di PtrType per 0 e NULL come int, che non implicitamente convertire in un tipo di puntatore.

Se volete vedere quello che voglio dire, basta provare la memorizzazione 0 e NULL in un auto 'd variabile prima, e chiamando f1 un f2 da quelle variabili. Non verranno compilati.

0 e NULL espressi in modo implicito su un tipo di puntatore perché sono valori letterali, credo. Probabilmente c'è qualcosa nello standard ma penso che tu abbia capito il punto.

+0

Vale la pena notare che 'decltype (NULL)' potrebbe non essere 'int' su ogni compilatore. L'unico requisito è che il letterale possa essere convertito implicitamente in qualsiasi tipo di puntatore, quindi 'NULL' potrebbe essere definito come' nullptr'. – Pubby

+0

citazione @pubb? – Yakk

+2

[support.types]/3: "La macro NULL è una costante di puntatore nullo C++ definita dall'implementazione". [conv.ptr]/1: "Una costante puntatore nullo è un valore intero letterale con valore zero o un valore di tipo' std :: nullptr_t' ". – TartanLlama

Problemi correlati