2014-11-13 12 views
14

Per esempio:Si può distinguere un weak_ptr scaduto da uno non inizializzato?

std::weak_ptr<int> wp1(std::make_shared<int>()); 
std::weak_ptr<int> wp2; 

assert(PointsToValidOrExpiredObject(wp1)); 
assert(!PointsToValidOrExpiredObject(wp2)); 

È una tale funzione possibile?

Caso di utilizzo: il costruttore di una classe accetta std::weak_ptr<Foo> come dipendenza. Passare un oggetto scaduto è ok (potrebbe accadere in alcuni flussi di lavoro), ma il passaggio di null significa che il programmatore dimentica qualcosa. Mi piacerebbe testare questo come parte della validazione dei parametri del costruttore.

+0

Hai dato un'occhiata al metodo ['expired()'] (http://en.cppreference.com/w/cpp/memory/weak_ptr/expired)? – Borgleader

+0

@Borgleader. Sì - sfortunatamente, restituisce true per entrambi i casi. – dlf

+1

Anche se sembra che ci sia una risposta, una soluzione meno magica potrebbe essere quella di avvolgere il puntatore debole in un tipo che può essere costruito solo con un puntatore condiviso non vuoto e che richiede invece un puntatore debole non elaborato. –

risposta

16

std::weak_ptr::owner_before in grado di distinguere tra puntatori deboli che sono vuoti e scaduti. È quindi possibile implementare PointsToValidOrExpiredObject come:

template <typename T> 
bool PointsToValidOrExpiredObject(const std::weak_ptr<T>& w) { 
    return w.owner_before(std::weak_ptr<T>{}) || 
      std::weak_ptr<T>{}.owner_before(w); 
} 

Demo.

Regarding the original uncertainty I had about an expired weak_ptr still maintaining ownership: Ora sono certo che i requisiti generali di sicurezza del thread in tutta la biblioteca impongono che uno scaduto weak_ptr continui ad avere la stessa proprietà. In caso contrario, la distruzione dell'ultimo shared_ptr rimanente nel thread A dovrebbe modificare in modo osservabile lo stato di uno/alcuni/tutti weak_ptr s che condividono la proprietà con lo shared_ptr in questione. Se il thread B esaminava simultaneamente lo stato di tale weak_ptr, si avrebbe una corsa di dati introdotta dall'implementazione della libreria che è proibita in generale.

+0

Sembra proprio che sia così. I puntatori sono equivalenti "se condividono la proprietà o sono entrambi vuoti" e non c'è nulla che indichi che un puntatore debole diventa vuoto (e smette di condividere la proprietà) quando scade. –

+1

Ottimo! Ho dovuto cercare la documentazione di 'owner_before' per capire cosa significa e perché funziona. Per gli altri nella stessa situazione: puoi pensare a questa funzione come ad un 'operatore <' che, in pratica, confronta gli indirizzi. Quindi se questo dlf