Подтвердить что ты не робот

Почему std:: function не является допустимым параметром шаблона, а указатель функции?

Я определил шаблон класса с именем CallBackAtInit, который предназначен только для вызова функции при ее инициализации (конструкторе). Функция указана в параметрах шаблона. Проблема в том, что шаблоны не принимают std::function в качестве параметров; но они принимают указатели на функции. Почему?

Вот мой код:

#include <iostream>
#include <functional>

/* Does not work:*/     template <typename return_type, typename arg_type, std::function<return_type(arg_type)> call_back>
/* Work fine: *///      template <typename return_type, typename arg_type, return_type(*call_back)(arg_type)>

class CallBackAtInit {
public:
    CallBackAtInit(arg_type arg)
    {
        call_back(arg);
    };
};

void printInt(int i);

class HoldInt : private CallBackAtInit<void, int, printInt> {
public:
    HoldInt(int integer)
    : CallBackAtInit(integer)
    {}
    // ...
};

int main(int argc, char** argv)
{
    HoldInt hi(10);
    return 0;
}

void printInt(int i)
{
    std::cout << i << std::endl;
}
4b9b3361

Ответ 1

Параметр для определения шаблона может быть четырех видов:

  • который может принимать только тип (или тип шаблона).
  • который может принимать только интегральное значение.
  • который может принимать только значение указателя на элемент.
  • std::nullptr_t (начиная с С++ 11)

Когда вы указываете std::function в определении шаблона, то он не попадает ни в одну из вышеперечисленных категорий. Шаблон не может принимать типы и не может принимать целочисленное значение или значение указателя на элемент.

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

Ответ 2

Потому что это запрещено стандартом:

14.1 Параметры шаблона

4 Параметр шаблона, не относящийся к типу, должен иметь одно из следующих (необязательно cv-qualified):

- интегральный или перечисляемый тип,

- указатель на объект или указатель на функцию,

- ссылка lvalue на ссылку объекта или lvalue на функцию,

- указатель на член,

- std:: nullptr_t.