Boost logo

Boost :

Subject: Re: [boost] [variant2] Need rationale for never-empty guarantee
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2019-03-02 22:31:49

>> You see, I would consider any union-based storage as in the same
>> category. By definition union-based storage must contain a "pointer" to
>> the correct way to interpret that union-based storage.
> I don't understand this. Andrzej says pointers and
> means it literally: T*. You say "pointers" and
> I have no idea what you mean by it and what relation
> it has to exception safety.

If an object *selects* another object, then in my opinion it needs to
propagate the strongest possible exception guarantees it can for
assignment, swap and emplace.

If an object *aggregates* other objects, then in my opinion it is
permitted to have partial operations. So swap can get half way into
swapping the individual members in the aggregate, and bail out.

This might help:

T*: Selects a T[1...N]
unique_ptr<T[x]>: Selects a T[x]
vector<T>: Selects a T[0...N]
optional<T>: Selects a T[0], or a T[1]
variant<A, B, C>: Selects one of a A[1], B[1], or C[1], with all others [0]

struct: Aggregate of heterogeneous types
T[x]: Aggregate of x homogeneous T's
array<T, x>: Aggregate of x homogeneous T's
Can you see the difference yet? The first group selects an aggregate
*elsewhere*. The second grouo IS an aggregate.
The first group, being a "selector" of a type, ought to have very strong
guarantees. Modifying them ought to all-or-nothing transactions. No half
way states. Like you wouldn't expect modifying a string_view could ever
update just the beginning without updating the end.
The second group it would be too inefficient to implement
transactionally, at least for C++. We have seen this already in memory
transaction supporting compilers. So we permit half-way-house aborts,
and the programmer needs to know they must clean that up explicitly.
All the above enables the simple rule:
1. Single selectors of objects are safe in global state when exceptions
can be thrown.
2. Aggregates of objects in global state must be specially cleaned up,
or be idempotent, when exceptions can be thrown.
I know I write my code this way, which is why std::variant annoys me so

Boost list run by bdawes at, gregod at, cpdaniel at, john at