2014-11-13 87 views
6

Quando guardo i requisiti Container su cppreference, elenca Destructible come requisito per value_type. Ciò sembra implicare che i distruttori degli elementi del contenitore non possano gettare.Gli elementi in un vettore std :: hanno un distruttore di lancio?

Non sono stato in grado di trovare una citazione per questo requisito nello standard C++ 14 (non ho cercato nelle versioni precedenti). L'unica cosa che posso trovare è che value_type deve essere Erasable che non implica alcuna eccezione di sicurezza.

Quindi la mia domanda è, possono gli elementi in un std::vector hanno un distruttore di lancio? In caso contrario, quale sezione della norma lo proibisce?


P.S .: Non preoccuparti, non ho intenzione di creare tipi con il lancio di distruttori. Sto solo scrivendo un'implementazione conforme allo standard e sto cercando di ottenere la massima sicurezza.

+0

La Tabella 14 nello standard C++ 11 dice la stessa cosa che il tuo cppreference dice di Destructible: "nessuna eccezione viene propagata". –

+3

cppreference aggiornato per concordare con la Tabella 96, scusa per aver reso la tua domanda obsoleta – Cubbi

+0

@TonyD La mia domanda non riguarda Destructible, riguarda 'std :: vector'. – orlp

risposta

4

N4140 [res.on.Funzioni]/2 stati:

In particolare, gli effetti non sono definite nei seguenti casi:

(2.1) - per funzioni di sostituzione (18.6.1), se la funzione di sostituzione installato non implementa la semantica del comportamento richiesto applicabile: paragrafo.

(2,2) - per funzioni di gestione (18.6.2.3, 18.8.3.1, D.11.1), se la funzione di gestione installato non implementa la semantica del comportamento richiesto applicabile: il paragrafo

(2,3) - per i tipi utilizzati come argomenti del modello durante l'istanziazione di un componente del modello, se le operazioni sul tipo non implementano la semantica della sottoclavi Requirements applicabile (17.6.3.5, 23.2, 24.2, 26.2). Le operazioni su tali tipi possono segnalare un errore lanciando un'eccezione se non diversamente specificato.

(2.4) - se qualsiasi funzione di sostituzione o funzione di gestione o operazione di distruttore termina tramite un'eccezione , a meno che non sia specificamente consentito nel comportamento Richiesto applicabile: paragrafo.

(2.5) - se un tipo incompleto (3.9) viene utilizzato come argomento modello durante l'istanziazione di un componente modello, a meno che non sia specificamente consentito per tale componente.

Che è un po 'oscuro, ma consente di risparmiare un sacco di spazio che altrimenti sarebbe sprecato in "T deve soddisfare i requisiti distruttibili" dichiarazioni in tutto le clausole della biblioteca.

In particolare, ciò non implica che gli elementi di un std::vector non possano avere un distruttore di lancio; significa solo che il suddetto distruttore non deve mai lanciare quando chiamato dalla libreria standard. Quindi ad es. questo programma è conforme:

#include <vector> 

struct A { 
    bool throw_an_int = false; 
    ~A() noexcept(false) { 
    if (throw_an_int) throw 42; 
    } 
}; 

int main() { 
    try { 
    A a; 
    a.throw_an_int = true; 
    std::vector<A> lots_of_As(42); 
    } catch(int&) {} 
} 
1

Sì. e pugnale; Lo standard dice in requisiti generali:

[C++11: §23.2.1/10]:

Se non diversamente specificato (si veda 23.2.4.1, 23.2.5.1, 23.3.3.4 e 23.3.6.5 ) tutti i tipi di contenitori definiti nel questa clausola soddisfa i seguenti requisiti aggiuntivi:

- nessuna funzione di cancellazione(), cancellazione(), pop_back() o pop_front() genera un'eccezione.

Utilizzando la funzione clear come esempio (a causa di non essere un'eccezione all'obbligo generale) ha i seguenti requisiti:

distrugge tutti gli elementi di una. Invalida tutti i riferimenti, i puntatori e gli iteratori che si riferiscono agli elementi di a e possono invalidare l'iteratore passato-fine. Messaggio: a.empty() rendimenti true

Il che significa che si chiama essenzialmente la std::allocator_traits<Alloc>::destroy su tutti gli elementi. Che delega a t->~T() se a.destroy(t) non è disponibile. Tuttavia questo garantisce implicitamente che né a.destroy(t)t->~T() dovrebbe buttare perché sarà viola s' clear forte noexcept specifica:

// § 23.3.6.1 
void clear() noexcept; 

Così, attraverso la deduzione si potrebbe affermare che i distruttori possono gettare ma devono essere soppressi attraverso un meccanismo tale come avvolgerli in un blocco try-catch.

& pugnale ;: Ulteriori controlli in seguito, sembra che i distruttori può tiro, ma le eccezioni devono essere soppressi, come indicato nei commenti qui sotto.

+1

Ma ciò non proibisce 'void clear() noexcept {try {_ActualClear(); } catch (...) {}} 'implementazione, vero? –

+0

Come dice @Joker_vD, 'noexcept' non garantisce che nessuna esecuzione di una funzione possa generare un'eccezione generata, è una garanzia che non verranno emesse eccezioni da tale funzione. – Casey

+0

Quindi un allocatore personalizzato potrebbe fornire un 'destroy' di soppressione dell'eccezione, permettendo a' value_type' di avere un distruttore di lancio .. non dovrebbe la prima riga dire "Sì"? – Cubbi