Skip to content

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

@Gregory-Meyer

Description

@Gregory-Meyer

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions