Reputation: 42759
The purpose behind my question is to use std::map
(ie insertion, deletion, access) with guarantee that no exception will throw from std::map
implementation.
Deletion is not a problem, neither access if one use things carefully (no at
without check for example).
But insertion is another problem. In this code:
#include <map>
struct foo{};
int main()
{
std::map<int, foo> my_map;
my_map.insert(std::pair<int, foo>(42, foo{}));
}
my_map
do some allocation and throw if there is no more memory.
Now, what I want is a way to do this:
#include <map>
struct foo{};
int main()
{
std::map<int, foo> my_map;
auto my_new_pair{ new std::pair<int, foo>(42, foo{}) };
if (my_new_pair) // ok, we could build the node
{
my_map.insert(my_new_pair); // no allocation, my_map only takes the "ownership" of my_new_pair
}
}
but there is no such overload of insert
.
Do you guys have a solution?
Upvotes: 1
Views: 698
Reputation: 477040
Use node extraction and transplanation:
{
std::map<int, foo> staging_map;
staging_map.emplace(42, foo{});
real_map.insert(staging_map.extract(42)); // cannot throw
}
You're not quite doing the allocation "yourself", but you basically can get hold of a pre-allocated map node with this approach that you can use to your own ends until you're ready to insert it into the map, e.g.:
auto nh = staging_map.extract(42);
// Done initializing.
// use nh freely
real_map.insert(std::move(nh)); // guaranteed to work
Upvotes: 2
Reputation: 21576
The purpose behind my question is to use std::map (ie insertion, deletion, access) with guarantee that no exception will throw from std::map implementation.
If you leave the default std::allocator
in place when instantiating a
std::map<
Key, T, Com=std::less<
Key>
, Allocator=std::allocator<...>
>
;
then you cannot make any exception guarantees. in inserts
or emplace
.
23.2.1/8: Unless otherwise specified, all containers defined in this clause obtain memory using an allocator
I don't see how its possible to do inserts without memory allocation in most STL implementations because they mostly make use of Red Black Trees with heap allocated nodes. You may want to use a custom allocator that allocates from an existing memory pool, with noexcept guarantees. Or write your own container.
Upvotes: 2