Can elements in std :: vector throw a destructor?

When I look at the Container cppreference requirements, it lists Destructible as the requirement for value_type . This, apparently, means that the container element destructors cannot get out.

I could not find a link to this requirement in the C ++ 14 standard (I did not look in older versions). The only thing I can find is that value_type should be Erasable , which does not imply any exception safety at all.

So my question is: can elements in std::vector throw a destructor? If not, which section of the standard prohibits?


PS: Don’t worry, I do not plan to create types with throwing destructors. I am just writing a standard implementation and trying to get the exception right.

+6
source share
2 answers

N4140 [res.on.functions] / 2:

In particular, the effects are undefined in the following cases:

(2.1) - for replacement functions (18.6.1), if the established replacement function does not implement the semantics of the applicable Mandatory Behavior: paragraph.

(2.2) - for handler functions (18.6.2.3, 18.8.3.1, D.11.1), if the established handler function does not implement the semantics of the applicable mandatory behavior: paragraph

(2.3) - for types used as template arguments when creating an instance of a template component, if operations on the type do not implement the semantics of the applicable subtask Requirements (17.6.3.5, 23.2, 24.2, 26.2). Operations on these types may report an error, throwing an exception unless otherwise specified.

(2.4) - if any replacement function or handler function or destructor operation terminates through an exception, unless this is permitted in the applicable mandatory behavior: paragraph.

(2.5) - if the incomplete type (3.9) is used as a template argument when creating an instance of a template component, if this is not specifically permitted for this component.

This is a bit obscure, but it saves a lot of space that would otherwise have been wasted on " T should follow the Destructible Requirements instructions in all sections of the library.

Remarkably, this does not mean that a std::vector elements cannot have a crushing thrower; this means that the specified destructor should never be thrown when called from the standard library. So, for example, this program corresponds to:

 #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&) {} } 
+4
source

Yes. & dagger; The standard refers to this in general requirements:

<sub> [C++11: Β§23.2.1/10]: sub>

Unless otherwise specified (see 23.2.4.1, 23.2.5.1, 23.3.3.4 and 23.3.6.5), all container types defined in this section satisfy the following additional requirements:

- the function erase (), clear (), pop_back () or pop_front () does not throw an exception.

Using the clear function as an example (because of this, it is no exception to the general requirement), it has the following requirements:

Destroys all elements in a. The invalidity of all references, pointers, and iterators related to the elements of a can invalidate the iterator of the past end. Message: a.empty() returns true

This means that it essentially calls std::allocator_traits<Alloc>::destroy for all elements. To whom t->~T() delegated if a.destroy(t) not available. However, this implicitly guarantees that neither a.destroy(t) nor t->~T() should be thrown because it violates the clear strong noexcept :

 // Β§ 23.3.6.1 void clear() noexcept; 

Thus, thanks to the deduction, we could argue that destructors can throw, but they need to be suppressed using some mechanism, for example, wrapping them in a try-catch block.

& dagger ;: Upon further inspection, it seems that destructors can throw, but exceptions should be suppressed, as indicated in the comments below.

+1
source

Source: https://habr.com/ru/post/978120/


All Articles