Вам нужен type-id, который по сути точно совпадает с объявлением, кроме удаления declarator-id. declarator-id обычно является идентификатором и именем, которое вы объявляете в декларации equivilant.
Например:
int x
declarator-id - x, поэтому просто удалите его:
int
Аналогично:
int x[10]
Удалите x:
int[10]
В вашем примере:
void (*FunctionPtr)()
Здесь declarator-id есть FunctionPtr. поэтому просто удалите его, чтобы получить type-id:
void (*)()
Это работает, потому что, учитывая type-id, вы всегда можете однозначно определить, куда будет идти идентификатор, чтобы создать объявление. Из 8.1.1 в стандарте:
Можно однозначно идентифицировать местоположение в [type-id], где будет отображаться идентификатор если строительство было [декларация]. Именованный тип тогда совпадает с типом гипотетический идентификатор.
Ответ 4
Как насчет этого синтаксиса для ясности? (Обратите внимание на двойную скобку)
void func();
using FunctionPtr = decltype((func));