make_tuple - tuple c++ example




C++ std:: ordine di distruzione della tupla (2)

Con Clang 3.4 ottengo lo stesso ordine di distruzione per std::pair e 2 element std::tuple e con g ++ 5.3 ottengo un ordine opposto che potrebbe essere principalmente dovuto all'implementazione ricorsiva di std::tuple in libstd ++.

Quindi, in pratica si riduce a quello che ho detto nel commento, è l'implementazione definita.

Dalla relazione BUG :

Commento di Martin Sebor

Poiché il layout dei membri di std :: pair è completamente specificato, lo stesso vale per l'ordine di inizializzazione e distruzione. L'output del test case riflette questo ordine.

L'ordine di inizializzazione (e distruzione) di std: stupro subobjects è specificato meno chiaramente. Almeno non è immediatamente evidente dalla mia lettura delle specifiche se è richiesto un ordine particolare.

Il motivo per cui l'output per std :: tuple con libstdc ++ è il contrario di std :: pair è perché l'implementazione, che si basa sull'ereditarietà ricorsiva, memorizza e costruisce gli elementi tuple nell'ordine inverso: cioè, la classe base, che memorizza il ultimo elemento, viene memorizzato e costruito per primo, seguito da ogni classe derivata (ognuno dei quali memorizza l'ultimo - Nesimo elemento).

La citazione dalla norma [sezione 20.4.1] a cui il reporter del bug sta citando

1 Questo sottoclasse descrive la libreria tuple che fornisce un tipo di tupla come la tupla del modello di classe che può essere istanziata con qualsiasi numero di argomenti. Ogni argomento del template specifica il tipo di un elemento nella tupla. Di conseguenza, le tuple sono raccolte di valori eterogenee e di dimensioni fisse. Un'istanza della tupla con due argomenti è simile a un'istanza della coppia con gli stessi due argomenti . Vedi 20.3.

L'argomento contro questo fatto nel bug collegato è:

Essere descritti come simili non implica che siano identici in ogni dettaglio. std :: pair e std :: tuple sono classi distinte con requisiti diversi su ciascuna. Se ritieni che sia necessario comportarsi in modo identico sotto questo aspetto (cioè, avere i loro sottooggetti definiti nello stesso ordine) devi puntare al testo specifico che lo garantisce.

Esiste una regola che stabilisce in quale ordine vengono distrutti i membri di una tupla?

Ad esempio, se Function1 restituisce una std::tuple<std::unique_ptr<ClassA>, std::unique_ptr<ClassB>> in Function2 , allora posso essere sicuro che (quando viene lasciato lo scope di Function2 ) l'istanza di ClassB cui a dal secondo membro viene distrutto prima dell'istanza di ClassA cui fa riferimento il primo membro?

std::tuple< std::unique_ptr< ClassA >, std::unique_ptr< ClassB > > Function1()
{
    std::tuple< std::unique_ptr< ClassA >, std::unique_ptr< ClassB > > garbage;
    get<0>(garbage).reset( /* ... */ );
    get<1>(garbage).reset( /* ... */ );
    return garbage;
}

void Function2()
{
    auto to_be_destroyed = Function1();
    // ... do something else

    // to_be_destroyed leaves scope
    // Is the instance of ClassB destroyed before the instance of ClassA?
}

Lo standard non specifica l'ordine di distruzione per std::tuple . Il fatto che §20.4.1 / p1 specifica che:

Un'istanza della tupla con due argomenti è simile a un'istanza della coppia con gli stessi due argomenti.

Simile qui non è interpretato come identico e di conseguenza non è implicito che std::tuple debba avere un ordine di distruzione inverso dei suoi argomenti.

Data la natura ricorsiva di std::tuple più probabile è che l'ordine di distruzione sia in ordine con l'ordine dei suoi argomenti.

Baso anche le mie ipotesi su un bug report per GCC BUG 66699 dove nella discussione le mie supposizioni di cui sopra sono giustificate.

Detto questo, l'ordine di distruzione di std::tuple non è specificato.





stdtuple