Синтаксис неименованного указателя функции в С++

Я искал самый неприятный сингл, и я наткнулся на что-то вроде этого:

Foo bar(Baz()); // bar is a function that takes a pointer to a function that returns a Baz and returns a Foo

Это сильно отличается от типичного синтаксиса return-type(*name)(parameters). В скобках представлены скобки для списка параметров или они для имени?

Ответ 1

Полностью явный вид:

Foo bar(Baz f());

bar - это функция, которая принимает один параметр f, который является функцией (без аргументов), возвращающей Baz.

Без указания параметра:

Foo bar(Baz ());

Причина bar заканчивает принимать указатель на функцию в том, что функции не могут быть переданы по значению, так объявить параметр как функция автоматически затухает его в указатель. Вышеуказанное выражение эквивалентно:

Foo bar(Baz (*)());

// or:
Foo bar(Baz (*f)());  // with a named parameter

Это похоже на void foo(int [10]) где int [10] также означает int * в списке параметров.

Ответ 2

В декларации есть два набора круглых скобок. Внешний набор круглых скобок представляет собой список аргументов bar функций:

Foo bar(Baz());
       ^     ^

Baz() в этом объявлении - это тип функции. Скобки в объявлении типа функции ограничивают список аргументов этой функции.

Foo bar(Baz());
           ^^

Чтобы уточнить: в контексте объявления аргумента функции, тип функции настраивается как указатель на функцию этого типа. Таким образом, декларация фактически эквивалентна:

Foo bar(Baz(*)());
           ^ ^

Выделенные круглые скобки этого альтернативного указателя аргументов указателя не присутствуют в объявлении "unadjusted".

Соответствующее стандартное правило:

[Dcl.fct]

Тип функции определяется с использованием следующих правил. Тип каждого параметра (включая пакеты параметров функций) определяется из его собственного decl-specifier-seq и declarator. После определения типа каждого параметра любой параметр типа "массив T" или типа функции T настраивается как "указатель на T"....

Ответ 3

В скобках представлены скобки для списка параметров или они для имени?

Они предназначены для списка параметров.

Так:

Foo bar(Baz());

объявляет функцию, которая принимает единственный параметр функции типа, который возвращает Baz и не принимает никаких параметров.

Это, по очереди, равно объявлению функции aa, которое принимает единственный параметр указателя типа на функцию, которая возвращает Baz и не принимает никаких параметров. как (из функции):

Тип каждого параметра функции в списке параметров определяется в соответствии со следующими правилами:

...

3) Если тип - это тип функции F, он заменяется типом "указатель на F"

...