Why do std::function instances have a default cons

2019-01-25 06:15发布

This is probably a philosophical question, but I ran into the following problem:

If you define an std::function, and you don't initialize it correctly, your application will crash, like this:

typedef std::function<void(void)> MyFunctionType;
MyFunctionType myFunction;
myFunction();

If the function is passed as an argument, like this:

void DoSomething (MyFunctionType myFunction)
   {
   myFunction();
   }

Then, of course, it also crashes. This means that I am forced to add checking code like this:

void DoSomething (MyFunctionType myFunction)
   {
   if (!myFunction) return;
   myFunction();
   }

Requiring these checks gives me a flash-back to the old C days, where you also had to check all pointer arguments explicitly:

void DoSomething (Car *car, Person *person)
   {
   if (!car) return;      // In real applications, this would be an assert of course
   if (!person) return;   // In real applications, this would be an assert of course
   ...
   }

Luckily, we can use references in C++, which prevents me from writing these checks (assuming that the caller didn't pass the contents of a nullptr to the function:

void DoSomething (Car &car, Person &person)
   {
   // I can assume that car and person are valid
   }

So, why do std::function instances have a default constructor? Without default constructor you wouldn't have to add checks, just like for other, normal arguments of a function. And in those 'rare' cases where you want to pass an 'optional' std::function, you can still pass a pointer to it (or use boost::optional).

7条回答
地球回转人心会变
2楼-- · 2019-01-25 07:22

Actually, your application should not crash.

§ 20.8.11.1 Class bad_function_call [func.wrap.badcall]

1/ An exception of type bad_function_call is thrown by function::operator() (20.8.11.2.4) when the function wrapper object has no target.

The behavior is perfectly specified.

查看更多
登录 后发表回答