Почему экземпляры std :: function имеют конструктор по умолчанию?

Это, вероятно, философский вопрос, но я столкнулся со следующей проблемой:

Если вы определите std :: function и не инициализируете ее правильно, ваше приложение будет аварийно завершено, например:

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

Если функция передается в качестве аргумента, вот так:

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

Тогда, конечно, это также вылетает. Это означает, что я вынужден добавить проверочный код следующим образом:

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

Требование этих проверок возвращает меня назад к старым дням Си, где вам также пришлось явно проверить все аргументы указателя:

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
   ...
   }

К счастью, мы можем использовать ссылки в C ++, что не позволяет мне писать эти проверки (при условии, что вызывающая сторона не передала содержимое nullptr в функцию:

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

Итак, почему экземпляры std :: function имеют конструктор по умолчанию? Без конструктора по умолчанию вам не пришлось бы добавлять проверки, как и для других нормальных аргументов функции. И в тех «редких» случаях, когда вы хотите передать «необязательную» функцию std ::, вы все равно можете передать указатель на нее (или использовать boost :: необязательный).