array icon indicating copy to clipboard operation
array copied to clipboard

Weak exception safety for flat_{set,map}::assign*()

Open Gregory-Meyer opened this issue 7 years ago • 1 comments

In flat_set::assign, the container only provides the basic exception guarantee if memory cannot be stolen from the input and the ::reserve() allocation throws. In addition, since input_view does not specify that its value_type is nothrow move or copyable, the operation may again fail during the translation of elements from the view into the set.

array_.clear();
array_.reserve(input.size()); // <-- might throw here, leaving the container empty

// insert all elements individually
for (auto& element : input.view())
{
    if (input.will_copy())
        insert(element); // <-- could also throw here, leaving a partially filled container
    else
    {
        // safe, according to precondition of input view,
        // we're allowed to move them
        auto& non_const = const_cast<Key&>(element);
        insert(std::move(non_const)); // <-- or here
    }
}

It looks like you are already aware of this, given the TODO comments in flat_map's assign* functions:

template <typename InputIt>
void assign_pair_range(InputIt begin, InputIt end)
{
    // TODO: exception safety
    clear();
    insert_pair_range(begin, end);
}

A simple solution to add strong exception safety would be to create a new flat_set from the input range and swap if there was no exception thrown.

Gregory-Meyer avatar Jul 12 '18 20:07 Gregory-Meyer

Yes, I'm aware of the issues.

I need to think about my exception safety policy for this library first, before fixing it. Right now I'm tending to providing the strong exception safety if a type has nothrow move constructors.

foonathan avatar Jul 13 '18 08:07 foonathan