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

Могли бы вы указать, какие именно ошибки возникают при выполнении данного кода?
Изображение к вопросу
  • 16 ноября 2023 г. 10:38
Ответы на вопрос 2
Нельзя передавать `std::function` как параметр шаблонной функции, потому что `std::function` является типом с определенным интерфейсом, который определен на этапе компиляции. В то время как шаблонные функции развертываются на этапе компиляции для каждого варианта типа, передавать `std::function` как параметр шаблона значило бы обобщить этот интерфейс, что невозможно.

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

1. Неоднозначность приложения шаблона: Если существует несколько возможных специализаций шаблона, которые работают с `std::function`, компилятор не сможет определить, какую из них использовать.

2. Несоответствие типов: Если тип переданной `std::function` не соответствует ожидаемому типу, возникнет ошибка компиляции.

3. Неопределенная специализация: Если не существует специализации шаблона, работающего с `std::function`, вы получите ошибку компиляции, что функция не определена для данного типа.

Вместо использования `std::function` вы можете использовать шаблонные параметры функции для достижения того же результата.
Потому что lambda-функция не эквивалентна std::function. Например: https://godbolt.org/z/YrKc8q5q7, https://stackoverflow.com/questions/11774277/lambd....

Лямбда-функцию нельзя напрямую привести к типу std::function в данном случае. Чтобы выполнить преобразование, вам необходимо явно преобразовать лямбду в std::function:

std::function comp = [](int left, int right)
{
  return left < right;
};
Sort(vec, comp);

Компилятор не может выполнить преобразование, так как тип, к которому нужно выполнить преобразование, неизвестен - он зависит от шаблонного параметра T.

Еще один вариант - указать тип шаблона явно:

Sort(vec, [](int left, int right)
{
  return left < right;
});

Однако лучше всего не использовать std::function в шаблоне. Просто используйте шаблонный параметр U, предполагая, что у него есть оператор (int, int). Если в качестве аргумента не передать функцию или лямбду, код не будет компилироваться:

template 
void Sort(std::vector& vector, U comparison) {
    // Используйте comparison, как если бы это была std::function:
    if (comparison(1, 1)) return;
};

int main()
{
  std::vector vec = { 1, 2, 3, 4, 5, 7, 6, 9 ,8 };
  Sort(vec, [](int left, int right) -> bool
  {
    return left < right;
  });
  return 0;
}
Похожие вопросы