Параметр указателя функции без звездочки

Я видел это определение функции, которая получает указатель на функцию в качестве параметра:

double fin_diff(double f(double), double x, double h  = 0.01) {
  return (f(x+h)-f(x)) / h;
}

Я привык видеть это определение со звездочкой, то есть:

double fin_diff(double (*f)(double), double x, double h  = 0.01);

Знаете ли вы, почему первое определение также верно?

Ответ 1

Стандарт говорит, что эти две функции эквивалентны, так как аргументы функции настроены так, чтобы быть указателем на аргументы функции:

16.1 Перегружаемые объявления [over.load]
(3.3) Объявления параметров, которые отличаются только тем, что один является типом функции, а другой является указателем на тот же тип функции, эквивалентны. То есть тип функции настраивается, чтобы стать указателем на тип функции (11.3.5).

то же самое в C:

6.7.5.3 Деклараторы функций (включая прототипы)
8 Объявление параметра как типа, возвращающего функцию, должно быть настроено на указатель на тип, возвращающий функцию, как в 6.3.2.1.

Ответ 2

Указатели на функции своеобразны. Дана функция void f(); , ты можешь сделать

void (*fptr)() = f;
void (*fptr)() = &f;
void (*fptr)() = &&f;
void (*fptr)() = &&&f;

до бесконечности.

Точно так же, когда вы вызываете функцию через указатель на функцию, вы можете сделать

fptr();
(*fptr)();
(**fptr)();
(***fptr)();

до бесконечности.

Все рушится.

Ответ 3

Если параметр функции указан как объявление функции, то сам компилятор неявно корректирует параметр как указатель функции.

Это похоже на то, когда имя функции передается в качестве аргумента какой-либо другой функции, как, например,

fin_diff( func_name, 10.0 );

компилятор снова неявно преобразует указатель функции в указатель на функцию.