C ++ std :: tuple destruction order

Is there a rule that states in which order the members of std :: tuple are destroyed?

For example, if Function1 returns std::tuple<std::unique_ptr<ClassA>, std::unique_ptr<ClassB>> in Function2 , can I be sure that (when Function2 left), the ClassB instance referenced the second member is destroyed before the ClassA instance referenced by the first member?

 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? } 
+45
c ++ c ++ 11 std stdtuple
Aug 21 '16 at 20:25
source share
3 answers

The standard does not specify the destruction order for std::tuple . The fact that in ยง20.4.1 / p1 it is stated that:

Creating an instance of a tuple with two arguments is similar to creating a pair with the same two arguments.

Like here is not interpreted as identical , and therefore it does not imply that std::tuple should have the order of the reverse destruction of its arguments.

Given the recursive nature of std::tuple , it is most likely that the order of destruction is ordered by the order of its arguments.

I also base my assumptions on the bug report for GCC BUG 66699 , where in the discussion my assumptions above are justified.

However, the kill order for std::tuple not specified.

+33
Aug 21 '16 at 21:06
source share

I offer a life lesson that I learned, not a direct answer, in response to your question:

If you can formulate a reasonable argument for several alternatives in favor of why this alternative should correspond to that provided by the standard, then you should not assume that any of them has a mandate (even if one of them happens).

In the context of tuples - please be kind to the people who support your code and do not let the order of destruction of elements of a tuple potentially ruin the destruction of other elements. This is just evil ... imagine a poor programmer who needs to debug this thing. In fact, this poor soul can be itself in a few years, when you have already forgotten about your tricky per-day trick.

If you absolutely must rely on the order of destruction, perhaps you should just use the correct class with tuple elements as your data members (for which you could write a destructor, making it clear what should happen in which order) or some other mechanism facilitating more explicit destruction control.

+52
Aug 21 '16 at 20:50
source share

With Clang 3.4, I get the same kill order for both std::pair and 2 std::tuple elements, and with g ++ 5.3 I get the opposite order, which can be mainly due to the recursive implementation of std::tuple in libstd + +.

So, it basically comes down to what I said in the comment, this implementation is defined.

From the BUG report:

Comment by Martin Sebor

Since the layout of the std :: pair elements is fully specified, the order of their initialization and destruction. The test case output reflects this order.

The order of initialization (and destruction) of std: stuple subobjects is less clearly indicated. At least this is not immediately apparent from my reading of the specification if any particular order is required.

The reason that the output of std :: tuple with libstdC ++ is the inverse of std :: pair is because an implementation that relies on recursive inheritance, saving and constructing tuple elements in the reverse order is: that is, the base class that stores the last the element is saved and built first, followed by each derived class (each of which stores the last - the Nth element).

A quote from the standard [section 20.4.1] that the error reporter cites

1 This subclause describes a tuple library that provides a tuple; enter as a tuple a class template that can be created using any number of arguments. Each template argument indicates the type of element in the tuple. Consequently, tuples are heterogeneous, collections of fixed sizes. Creating a tuple with two arguments is similar to an instance of a pair with the same two arguments . See 20.3.

An argument against this in a related error:

Being described as similar does not mean that they are the same in every detail. std :: pair and std :: tuple are different classes with different requirements for each. If you think that they should behave identically in this regard (that is, they have their subobjects defined in the same order), you must indicate the specific wording that guarantees this.

+13
Aug 21 '16 at 20:37
source share



All Articles