Topic: Throwing an exception from a functor involved in an STL algorithm?


Author: Simon.Richter@hogyros.de (Simon Richter)
Date: Tue, 7 Aug 2007 21:13:15 GMT
Raw View
Hi,

Michael wrote:

> With regard to the exception quest, I was really asking for two things
> (I should have been more explicit)

> 1. In the case of an exception that has std::exception in the
> inheritance hierarchy, I assume it blindy passes it along?
> 2. In the case of an exception that *doesn't* have std::exception in
> it's inheritance hierarchy, how does it handle this?

I think there should not be any difference in behaviour between those --
std::exception is an interface that people use by convention.

I would assume that throwing an exception from a functor will leave the
object currently handled in the state it was in at the point of the
throw (unless objects going out of scope during the throw further modify
it, such as locks being released[1]), and then terminate the loop.

There is no "roll-back" mechanism implied in functors throwing -- to
implement that, the objects inside the container would have to be
copyable and assignable, neither of which is required by all container
types in existance.

    Simon

[1] but there are people who argue that locks cannot really be called
"state"

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Simon.Richter@hogyros.de (Simon Richter)
Date: Wed, 8 Aug 2007 01:44:09 GMT
Raw View
Hi,

Michael wrote:

> With regard to the exception quest, I was really asking for two things
> (I should have been more explicit)

> 1. In the case of an exception that has std::exception in the
> inheritance hierarchy, I assume it blindy passes it along?
> 2. In the case of an exception that *doesn't* have std::exception in
> it's inheritance hierarchy, how does it handle this?

I think there should not be any difference in behaviour between those --
std::exception is an interface that people use by convention.

I would assume that throwing an exception from a functor will leave the
object currently handled in the state it was in at the point of the
throw (unless objects going out of scope during the throw further modify
it, such as locks being released[1]), and then terminate the loop.

There is no "roll-back" mechanism implied in functors throwing -- to
implement that, the objects inside the container would have to be
copyable and assignable, neither of which is required by all container
types in existance.

    Simon

[1] but there are people who argue that locks cannot really be called
"state"

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Michael <Michael.Reiland@gmail.com>
Date: Fri, 3 Aug 2007 09:36:35 CST
Raw View
I don't have access to the C++ standard, but what are the guarantees
with regards to exceptions?  For example.

class functor
{
  operator()(container_item i){/* do something */}
};

int main()
{
 functor fun;

 std::for_each(container.begin(), container.end(), fun);
 return 0;
}


1. Assume that the functor is not changing the state of the container
(ie, "read only"), is it safe?
2. If functor *is* changing the state of the container, what, if any,
guarantees does the standard give about the final state of the
container?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: David Abrahams <dave@boost-consulting.com>
Date: Fri, 3 Aug 2007 13:16:09 CST
Raw View
on Fri Aug 03 2007, Michael <Michael.Reiland-AT-gmail.com> wrote:

> I don't have access to the C++ standard, but what are the guarantees
> with regards to exceptions?

Yes.

> For example.
>
> class functor
> {
>   operator()(container_item i){/* do something */}
> };
>
> int main()
> {
>  functor fun;
>
>  std::for_each(container.begin(), container.end(), fun);
>  return 0;
> }
>
>
> 1. Assume that the functor is not changing the state of the container
> (ie, "read only"), is it safe?

What do you mean by "safe?"

> 2. If functor *is* changing the state of the container, what, if any,
> guarantees does the standard give about the final state of the
> container?

Only that the container could be in any state the functor might put it
into, and the elements are passed to the functor in order from begin()
to end().

--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

The Astoria Seminar ==> http://www.astoriaseminar.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: jpalecek@web.de
Date: Fri, 3 Aug 2007 15:52:23 CST
Raw View
On 3 Srp, 17:36, Michael <Michael.Reil...@gmail.com> wrote:
> I don't have access to the C++ standard, but what are the guarantees
> with regards to exceptions?  For example.
>
> class functor
> {
>   operator()(container_item i){/* do something */}
>
> };
>
> int main()
> {
>  functor fun;
>
>  std::for_each(container.begin(), container.end(), fun);
>  return 0;
>
> }
>
> 2. If functor *is* changing the state of the container, what, if any,
> guarantees does the standard give about the final state of the
> container?

If your functor is changing the container whose elements it is
operating
on (eg. via global variable), I would be very careful. Depending on
the
actual operation and type of container, you may be invoking undefined
behaviour by invalidating the iterators passed to for_each. Eg.
inserting
all iterated elements to the front of a list is ok, the same thing
with a
vector is not. Speaking for myself, I always write such notrivial
operations (ie. mutating the containers) usign loops.

A totally different story is if your functor only modifies the items,
not
the container itself. This is OK unless the container is immutable
(like sets).

If you're asking about exception safety of for_each with functor
that modifies the items and can throw, you'll only get the Basic
guarantee. And you're not probably gonna get much more, because
even if you wanted to compensate the effect of the functor in case
of exception, it will be hard to get which of the items were
processed.
(However, it may not be impossible, at least in special cases).

If the functor doesn't modify your original container,
then it's by definition at least Strong guarantee.

Regards
    Jiri Palecek

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Michael <Michael.Reiland@gmail.com>
Date: Sat, 4 Aug 2007 01:12:08 CST
Raw View
On Aug 3, 9:52 pm, jpale...@web.de wrote:
> On 3 Srp, 17:36, Michael <Michael.Reil...@gmail.com> wrote:
>
>
>
> > I don't have access to the C++ standard, but what are the guarantees
> > with regards to exceptions?  For example.
>
> > class functor
> > {
> >   operator()(container_item i){/* do something */}
>
> > };
>
> > int main()
> > {
> >  functor fun;
>
> >  std::for_each(container.begin(), container.end(), fun);
> >  return 0;
>
> > }
>
> > 2. If functor *is* changing the state of the container, what, if any,
> > guarantees does the standard give about the final state of the
> > container?
>
> If your functor is changing the container whose elements it is
> operating
> on (eg. via global variable), I would be very careful. Depending on
> the
> actual operation and type of container, you may be invoking undefined
> behaviour by invalidating the iterators passed to for_each. Eg.
> inserting
> all iterated elements to the front of a list is ok, the same thing
> with a
> vector is not. Speaking for myself, I always write such notrivial
> operations (ie. mutating the containers) usign loops.
>
> A totally different story is if your functor only modifies the items,
> not
> the container itself. This is OK unless the container is immutable
> (like sets).
>
> If you're asking about exception safety of for_each with functor
> that modifies the items and can throw, you'll only get the Basic
> guarantee. And you're not probably gonna get much more, because
> even if you wanted to compensate the effect of the functor in case
> of exception, it will be hard to get which of the items were
> processed.
> (However, it may not be impossible, at least in special cases).
>
> If the functor doesn't modify your original container,
> then it's by definition at least Strong guarantee.
>
> Regards
>     Jiri Palecek
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-...@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ:http://www.comeaucomputing.com/csc/faq.html                     ]

Thanks for the responses everyone.


The functor is modifying pod's in the container, not the container
itself.


With regard to the exception quest, I was really asking for two things
(I should have been more explicit)

1. In the case of an exception that has std::exception in the
inheritance hierarchy, I assume it blindy passes it along?
2. In the case of an exception that *doesn't* have std::exception in
it's inheritance hierarchy, how does it handle this?

What does the standard have to say about this?


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Sat, 4 Aug 2007 15:24:37 GMT
Raw View
Michael ha scritto:
> With regard to the exception quest, I was really asking for two things
> (I should have been more explicit)
>
> 1. In the case of an exception that has std::exception in the
> inheritance hierarchy, I assume it blindy passes it along?
> 2. In the case of an exception that *doesn't* have std::exception in
> it's inheritance hierarchy, how does it handle this?
>
> What does the standard have to say about this?
>

Whenever exceptions are thrown by user code, the standard library never
differentiate between exceptions derived from std::exception and those
which aren't. It would be simply wrong to do that.

Ganesh

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]