Weak exception safety for flat_{set,map}::assign*()
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.
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.