Почему возможно передавать указатели на функции в качестве параметров шаблона в C ?

#c #templates

#c #шаблоны

Вопрос:

Давайте рассмотрим выдержку:

 void myFunc(int a, int b) {}

template<void(*function_pointer)(int, int)> 
class TakeFunctionPointer {
public:
  TakeFunctionPointer() {
    function_pointer(5, 6);
  }
};

int main() {
  TakeFunctionPointer<myFunc> tfp{};
}
  

Этот код скомпилирован отлично, и он работает, но меня беспокоит, почему компилятор позволяет помещать указатели на функции в параметры шаблона, потому что, как я знаю, шаблоны в C являются частью статического полиморфизма, и ожидается, что сначала компилятор создает экземпляры всех классов шаблонов, а затем запускает их. Итак, это означает, что компилятор может принимать адрес функции с заданной сигнатурой и фактически помещает адрес. Это позволяет классу вызывать удобную функцию.
Как так получилось?

Комментарии:

1. Почему это не должно быть возможно?

2. Если это не достаточно странно, вы также можете иметь указатели на глобальные переменные в качестве параметров шаблона.

3. @Justin Скорее я имел в виду, что меня интересует, на каком шаге компилятор имеет информацию об адресе объекта…

Ответ №1:

Почему компилятор позволяет помещать указатели на функции в параметры шаблона?

Потому что стандарт говорит, что это разрешено.

Итак, это означает, что компилятор может принимать адрес функции с заданной сигнатурой и фактически помещает адрес.

Правильно.

Комментарии:

1. Очень короткий и лаконичный ответ! 🙂

Ответ №2:

Существует разница между class аргументами шаблона типа и аргументами типа значения. Если у вас есть шаблон, в котором уже задан фактический тип, например

 template<std::size_t N> /* class or function... */
  

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

 template<void(*function_pointer)(int, int)> /* ... */
  

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

Обратите внимание, что использование указателей на функции, подобных этому, т. Е. Во время компиляции, возможно, потому что функции и их сигнатуры должны быть известны во время компиляции в любом случае.