2013-07-28 17 views
5

Quando creo un unique_ptr con deleter, funziona:unique_ptr non è sempre init con predefinito deleter

std::unique_ptr<Animal<Cat>, void(*)(Animal<Cat>*)> ptr(new Animal<Cat>, [](Animal<Cat> *ls) { 
    delete ls; 
}); 

Ma, questo codice sta gettando errore:

std::unique_ptr<Animal<Cat>, void(*)(Animal<Cat>*)> ptr; 
ptr = std::unique_ptr<Animal<Cat>, void(*)(Animal<Cat>*)>(new Animal<Cat>, [](Animal<Cat> *ls) { 
    delete ls; 
}); 

L'errore:

/usr/bin/../lib/c++/v1/memory:2561:13: error: static_assert failed "unique_ptr constructed with null function pointer deleter" 
       static_assert(!is_pointer<deleter_type>::value, 
       ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
note: in instantiation of member function 'std::__1::unique_ptr<Animal<Cat>, void (*)(Animal<Cat> *)>::unique_ptr' requested here 
      std::unique_ptr<Animal<Cat>, void(*)(Animal<Cat>*)> ptr; 
                   ^

Questa è la versione del compilatore:

Apple clang version 4.0 (tags/Apple/clang-421.0.60) (based on LLVM 3.1svn) 
Target: x86_64-apple-darwin12.4.0 
Thread model: posix 

Le classi di animali e gatti sono banali. This is the entire code.

risposta

10

Come a quanto pare non è possibile per impostazione predefinita, costruire un unique_ptr con un tipo di puntatore per un deleter. I unique_ptr costruttori sono dettagliate nel §20.7.1.2.1 [unique.ptr.single.ctor] che dice, tra le altre cose:

constexpr unique_ptr() noexcept;

4 Remarks: If this constructor is instantiated with a pointer type or reference type for the template argument D [the deleter type], the program is ill-formed.

qualcosa di simile a ciò che si vuole che sia conforme di serie:

unique_ptr<int, void(*)(int*)> ptr{nullptr,[](int*p){delete p;}}; 
// ... 
ptr.reset(new int(42)); 
10

Dopo aver letto la risposta di Casey sopra, ho cambiato il mio codice per usare i vecchi Functional piuttosto che lambda per farlo funzionare.

Questa è la mia soluzione:

struct Deleter { 
    void operator()(Animal<Cat>* ls) { 
     delete ls; 
    } 
}; 

int main() { 
    std::unique_ptr<Animal<Cat>, Deleter> ptr; 
    ptr = std::unique_ptr<Animal<Cat>, Deleter>(new Animal<Cat>); 
    return 0; 
} 
+1

Il razionale di questo comportamento 'unique_ptr' è cercare di informarvi al momento della compilazione che una funzione puntatore a NULL non è un buon deleter. È possibile sovrascrivere questo comportamento inviando esplicitamente un deleter nullptr. Ma la soluzione che hai scelto è invece meglio imho. –

+0

@HowardHinnant Controllerà nullptr in fase di runtime o proverà a chiamare quella funzione? – user877329

+0

@ user877329: Se viene chiamato '~ unique_ptr()' o 'reset()' e 'get_deleter() (get())' non è ben formato, si ottiene un comportamento indefinito. –

Problemi correlati