A function that takes an argument of type B&
is not a function that takes an argument of type D&
. While D&
is convertible to B&
, they are not the same type. If you could store a pointer to a function that takes B&
as a pointer to D&
, how would the compiler know when to convert the argument? (Note that the conversion sometimes requires adjusting a pointer)
The difference in std::function
is that the calling signature (here D&
) is part of the function object's type, and the called signature (here B&
) is part of the internal storage. So when you apply the function objects' operator()
the code that implements operator()(D&)
takes care of the conversion.