2015-04-27 23 views
7

A volte fa ho visto un codice come questo:intelligente deleter puntatore e "con" parola chiave con un nome "puntatore"

void* Create() 
{ 
    int* t{new int{10}}; 
    return t; 
} 

class Deleter 
{ 
    //uncomment in order to compile 
    //using pointer = void*; 
public: 
    void operator()(void* t) 
    { 
     delete t; 
    } 
}; 

unique_ptr<int, Deleter> ptr{Create()}; 

Non fa compila. Con VS2013 si dice:

error: C2440: 'initializing' : cannot convert from 'initializer-list' to 'std::unique_ptr' No constructor could take the source type, or constructor overload resolution was ambiguous

Ma se la linea rimuovere il commento using pointer = void*; funziona! Anche se cambio un nome di alias in qualcosa di diverso da pointer ottengo lo stesso errore. Sembra quindi che avere una direttiva using con il nome esatto pointer sia fondamentale. Ma perché? Non ho trovato nessuna spiegazione.

risposta

6

Il unique_ptr dichiarato con T=int. Tuttavia, constructors in std::unique_ptr non prende l'argomento T*, ma invece l'argomento pointer.

Questo tipo pointer definito come

std::remove_reference<Deleter>::type::pointer if that type exists, otherwise T* 

E quando non si forniscono Deleter::pointer finisce come int*, e, naturalmente, non può essere inizializzato da void* (da Create).

1

[C++11: 20.7.1.2/3] If the type remove_reference<D>::type::pointer exists, then unique_ptr<T, D>::pointer shall be a synonym for remove_reference<D>::type::pointer . Otherwise unique_ptr<T, D>::pointer shall be a synonym for T* . The type unique_ptr<T, D>::pointer shall satisfy the requirements of NullablePointer (17.6.3.3).

E 'necessario qui perché non hai operator()(int*) - si sta "hacking" in giro che per consentire operator()(void*) da utilizzare al posto rendendo il deleter finta che sia un deleter per void*.

Se il vostro deleter nel suo complesso rimane strettamente valido anche quando compila, non vorrei dire.

Problemi correlati