6
votes

I tried without success to find if this code could throw an exception :

std::function<void(void)>f=[]{};

According to the standard, the copy or move constructor of std::function are not noexcept. But I guess the lack of the noexcept keyword is due to the fact that std::function also wrap user defined functor object whose copy or move constructors could throw.

In my case an exception seems very unlikely but is it possible at all ?

1
This case specifically can't throw an exception, as far as I'm aware (well, except out-of-memory exceptions, but when you get those, you're in bigger trouble anyways).Xeo
@Xeo: flag as not a commentLightness Races in Orbit
Since std::function uses internal magic like type erasure, I think it always has to deal with the possibility of allocation failures. I guess you could implement a "small member optimization" for type erasure, but that might be extreme.Kerrek SB
@KerrekSB: Actually, the standard recommends a small buffer optimization atleast the size of member-function-pointer + void* (for the object pointer).Xeo
@Xeo: I see, that makes sense.Kerrek SB

1 Answers

8
votes

In my case an exception seems very unlikely but is it possible at all ?

In principle, yes. std::function will have to allocate memory to store the callable object it's initialised with, and if that memory is allocated dynamically then there's the possibility of failure.

In practice, in your case, no. In the words of a note in the specification, "Implementations are encouraged to avoid the use of dynamically allocated memory for small callable objects". A lambda with no captures is convertible to a function pointer, which is about as small as a callable object gets; so a good implementation should certainly store that without dynamic allocation. And of course, copying a pointer can't throw either.

Larger objects (including lambdas with many captures) will need dynamic allocation, and need to copy their captured objects or other state, and so can't offer a no-throw guarantee.