Для языковой разницы (сохраняются только объявления функций ниже, так как это то, что важно только)
void execute( void (&func)() );
void g();
int main() {
void (*fp)() = g;
execute(fp); // doesn't work
execute(&g); // doesn't work either
execute(g); // works
}
Это не работает, потому что оно хочет функцию, а не указатель на функцию. По той же причине, что ответ массива отклоняет указатель, он также отклоняет указатель. Вы должны передать «г» напрямую.
Для шаблонов это тоже имеет значение
template<typename T>
void execute(T &t) { T u = t; u(); }
template<typename T>
void execute(T t) { T u = t; u(); }
Эти двое сильно отличаются друг от друга. Если вы вызываете его с execute(g);
, как описано выше, то первый попытается объявить функцию и инициализировать ее с t
(ссылка на g
). Сгенерированная функция будет выглядеть так:
void execute(void(&t)()) { void u() = t; u(); }
Теперь вы можете инициализировать ссылки и указатели на функции, но, конечно, не сами функции. Во втором определении T
будет выведено к типу указателя функции путем вывода аргумента шаблона, и передача функции неявно преобразует его в этот тип параметра указателя. Так что все будет хорошо.
Я не знаю, почему MSVC трактует их по-разному для встраивания - но я также подозреваю, что это потому, что ссылки на функции появляются реже.