Передавать функцию как явный параметр шаблона

В приведенном ниже примере кода вызов foo работает, а вызов bar завершается с ошибкой.

Если я прокомментирую вызов bar, компиляция кода, которая говорит мне, что само определение bar отлично. Итак, как бы bar было вызвано правильно?

#include <iostream>

using namespace std;

int multiply(int x, int y)
{
    return x * y;
}

template <class F>
void foo(int x, int y, F f)
{
    cout << f(x, y) << endl;
}

template <class F>
void bar(int x, int y)
{
    cout << F(x, y) << endl;
}

int main()
{
    foo(3, 4, multiply); // works
    bar<multiply>(3, 4); // fails

    return 0;
}

Ответы

Ответ 1

Проблема здесь: multiply не является типом; это значение, но шаблон функции bar ожидает, что аргумент шаблона будет типом. Отсюда ошибка.

Если вы определяете шаблон функции как:

template <int (*F)(int,int)> //now it'll accept multiply (i.e value)
void bar(int x, int y)
{
    cout << F(x, y) << endl;
}

тогда это сработает. Смотрите онлайн-демонстрацию: http://ideone.com/qJrAe

Вы можете упростить синтаксис, используя typedef как:

typedef int (*Fun)(int,int);

template <Fun F> //now it'll accept multiply (i.e value)
void bar(int x, int y)
{
    cout << F(x, y) << endl;
}

Ответ 2

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

Наваз уже ответил на вопрос другим способом (как изменить определение bar для использования с функциями), но чтобы ответить на ваш явный вопрос о том, как вызвать bar, как у вас есть, вам нужно подходящий тип, например:

struct Type {
  const int result;
  Type(int x, int y): result(x * y) {}
  operator int() const { return result; }
};

// usage
bar<Type>(x, y);

// (edit) a suitable type doesn't necessarily mean a new type; this works as well
// if you aren't trying to solve any specific problem
bar<std::string>(64, 64);