Requirements of TR1 associative containers

Y

yonil

I hope this is the correct group for this...

I'm currently implementing the TR1 associative containers according to
specification found in
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1745.pdf.

Now I'm not sure how to interpret a requirement relating to exception
safety. It says in 6.3.1.1:
"For unordered associative containers, if an exception is thrown by any
operation other than the container's hash function from within an
insert() function inserting a single element, the insert() function has
no effect.".

Now, in the "range insertion" method: template <class InputIterator>
void insert(InputIterator first, InputIterator last)

the implementation inserts the elements one at a time, the question is
what to do if a single insert() throws an exception. I didn't
understand whether it's supposed to erase anything it inserted so far
(and btw, should it be erased in the reverse order to the insertions?),
or whether to simply return regardless of how many elements were
inserted.

I looked in the implementation of MSVC STL containers, and the code for
the equivalent function in <set> doesn't unwind the insertions. On the
other hand, inserting a range to a vector or a list seems to be a
transactional operation.

Also, if it is required to be transactional in the TR1 associative
containers, then for input iterators I'll have to make a temporary copy
of all the inserted values (e.g. a vector/stack) (right?), though for
forward or stronger categories there's no problem and I can simply
invoke erase(first, current) and rethrow.

I'm also wondering what happens if the erase operations throw? does
that mean the original exception is lost? also, does it mean you have
to do the range insert on a temporary copy of the unordered_set? I mean
otherwise the insertion won't be transactional in such case. I'm kinda
lost here.
 
M

Michiel.Salters

yonil said:
I hope this is the correct group for this...

I'm currently implementing the TR1 associative containers according to
specification found in
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1745.pdf.

comp.std.c++ is the better group.
Now I'm not sure how to interpret a requirement relating to exception
safety. It says in 6.3.1.1:
"For unordered associative containers, if an exception is thrown by any
operation other than the container's hash function from within an
insert() function inserting a single element, the insert() function has
no effect.".

Now, in the "range insertion" method: template <class InputIterator>
void insert(InputIterator first, InputIterator last)

the implementation inserts the elements one at a time.

That's an implementation detail. You're not bound by the interface
requirement
of the (public) single-element insert functions just because you reuse
that same
insert function internally.
The question is what to do if a single insert() throws an exception.

There's not a lot you can do? Just pass on the exception. There is no
requirement
to do rollback. Of course, the container should be in some sane state
(must be
able to be destroyed).
I didn't understand whether it's supposed to erase anything it inserted so far

Not AFAIK; I think vector and set have exactly the same restrictions.
I looked in the implementation of MSVC STL containers, and the code for
the equivalent function in <set> doesn't unwind the insertions.

Considering Dinkuware knows the standard a whole lot better than I do,
*and*
that they agree with me, I'd say we're both right then ;)
On the other hand, inserting a range to a vector or a list seems to be a
transactional operation.

It's definitely allowed, if you can do so.
Also, if it is required to be transactional in the TR1 associative
containers, then for input iterators I'll have to make a temporary copy
of all the inserted values (e.g. a vector/stack) (right?), though for
forward or stronger categories there's no problem and I can simply
invoke erase(first, current) and rethrow.

Are you confusing source iterator ranges and the associative iterator
ranges?
You know your own iterators. The source iterators are unspecified, but
once you
throw you're not using those to rollback.
I'm also wondering what happens if the erase operations throw? does
that mean the original exception is lost?

Yes, it would imply that, which is why it can't (again, AFAIK). The
assumption is
of course that the value_type dtor doesn't throw.
Also, does it mean you have to do the range insert on a temporary copy of the
unordered_set? I mean otherwise the insertion won't be transactional in such
case. I'm kinda lost here.

No; even if you needed transactional behavior you could just keep track
of the
iterators to erase if needed. But check in csc++ to be sure.

Regards,
Michiel Salters
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top