Вы не можете. Я подозреваю, что путаница связана с отсутствием различия между «функцией» и «шаблоном функции».
Чтобы объяснить, почему ваш первый пример сработал, сначала давайте рассмотрим, что на самом деле происходит, когда вы делаете run(a, ADD, linearAlgo);
. Напомним, что у нас есть:
template <typename dtype>
using AlgoFunction = double(*)(const std::vector<dtype>&, Op);
template <typename dtype>
std::vector<double> run(const std::vector<dtype>&, Op,
double(*)(const std::vector<dtype>&, Op));
Эквивалентно, мы могли бы иметь следующее:
std::vector<double> run(const std::vector<dtype>&, Op, AlgoFunction<dtype>);
, поскольку AlgoFunction
это просто псевдоним.
Теперь когда мы делаем это:
std::vector<double> a;
run(a, ADD, linearAlgo);
мы знаем, что первый аргумент run
, std::vector<dtype>
, это std::vector<double>
, и, следовательно, dtype
это double
. Мы ничего не можем определить относительно dtype
по третьему аргументу, поскольку linearAlgo
- это просто шаблон, «шаблон».
Поскольку мы знаем, что dtype
должно быть double
, мы можем выбрать и создайте экземпляр linearAlgo<dtype>
- то есть linearAlgo<double>
- как нашу функцию, поскольку она соответствует нашей подписи, и все в порядке.
Теперь, как это связано с этим?
AlgoFunction functor = reverseLinearAlgo;
В этом случае мы пытаемся создать переменную. reverseLinearAlgo
- это просто шаблон функции, а не фактическая функция, и у нас нет другого контекста, чтобы определить, какой тип functor
на самом деле. Отсюда ошибка компилятора.
Кроме того, что бы это на самом деле означало? Будет ли functor
иметь другой тип в зависимости от того, где вы его использовали? Если бы я сделал auto x = functor;
, какой бы тип имел x
? Если бы я сделал что-то вроде
AlgoFunction functor = reverseLinearAlgo;
if (test) {
std::vector<float> x;
functor(x, ADD);
} else {
std::vector<double> x;
functor(x, ADD);
}
, значит ли это, что functor
имеет тип Dynami c? Это не то, что работает с системой типов C ++ (stati c), и может быстро выйти из-под контроля, если это будет сделано законным. Это случай с вашим wi sh для std::vector<AlgoFunction>
: вы должны хранить конкретный тип. В противном случае программе потребуется динамически создавать функцию на основе информации времени выполнения: параметры шаблона должны быть известны во время компиляции.
Одна из возможных альтернатив, если вы знаете типы заранее, - это использовать std::variant
из возможных типов, с которыми вы можете создать экземпляр. То есть что-то вроде
std::vector<std::variant<AlgoFunction<float>, AlgoFunction<double>>>;
, если каждый элемент вектора должен предоставлять один или другой, или же использовать
std::vector<std::tuple<AlgoFunction<float>, AlgoFunction<double>>>;
, если каждый элемент вектора должен использоваться с type.
Полезно ли это и стоит ли сложность, решать только вам.