#c #function #templates
Вопрос:
Следующий фрагмент кода представляет собой урезанную версию того, что должно стать алгоритмом оптимизации:
template<typename F>
double helper(F f, double x)
{
return x;
}
template<typename F, typename L>
double optimize(F f, double x, L line_search)
{
double y = line_search(f, x);
return y;
}
int main()
{
auto f = [](double x){ return (x - 2) * (x - 2); };
double solution = optimize(f, -2, helper);
}
Я параметризовал основную функцию ( optimize
) и вспомогательную функцию ( helper
) с помощью аргумента шаблона F
для функции, которую они пытаются минимизировать. Однако код не компилируется; компилятор не может определить тип line_search
:
t04.cpp: In function ‘int main()’:
t04.cpp:17:45: error: no matching function for call to ‘optimize(main()::<lambda(double)>amp;, int, <unresolved overloaded function type>)’
double solution = optimize(f, -2, helper);
^
t04.cpp:8:8: note: candidate: template<class F, class L> double optimize(F, double, L)
double optimize(F f, double x, L line_search)
^~~~~~~~
t04.cpp:8:8: note: template argument deduction/substitution failed:
t04.cpp:17:45: note: couldn't deduce template parameter ‘L’
double solution = optimize(f, -2, helper);
(Я использую gcc v7.5.0, но я не думаю, что это имеет значение здесь.) Я думаю, что понимаю, почему компилятор не знает тип line_search
(он не заглядывает внутрь optimize
, чтобы увидеть, как line_search
это называется), но я не знаю, как объяснить, каким должен быть правильный тип. Хотел бы я сказать optimize(f, -2, helper<type of f>)
, но я не нашел, как это сделать. Что мне нужно изменить в коде?
Кстати, если есть другие, столь же общие способы разработки этого, но которые позволяют избежать проблемы вывода аргументов шаблона, мне было бы интересно узнать о них.
Комментарии:
1.
helper
это шаблон функции. В какой специализацииhelper
должен работать компиляторoptimize(f, -2, helper)
?2. Почему helper-это шаблон? Это ничего не делает с f. Если есть причина, то вы, возможно, могли бы сделать так
optimize(f, -2, helper<decltype(f)>)
.3. @ScottHutchinson: Вы правы, что в этом примере параметр шаблона не используется. Идея состоит в том, что может быть несколько помощников (на самом деле, методы поиска строк), которые выполняют одну и ту же задачу минимизации функции
f
одной переменной.decltype
на самом деле это то, что я искал, сам того не зная.
Ответ №1:
Вы можете добавить тип по умолчанию, для L
которого включает F
:
template<typename F>
double helper(F f, double x) {
return f(x);
}
template<typename F, typename L = double(*)(F, double)> // <- here
double optimize(F f, double x, L line_search) {
double y = line_search(f, x);
return y;
}
Затем он найдет правильный экземпляр шаблона, когда вы это сделаете
double solution = optimize(f, -2, helper); // helper is helper<decltype(f)>
Если helper
это шаблон функции, который вы часто используете, вы можете сделать его шаблоном по умолчанию:
template<typename F, typename L = double(*)(F, double)>
double optimize(F f, double x, L line_search = helper<F>) { // <- here
double y = line_search(f, x);
return y;
}
что позволяет звонить optimize
без указания помощника:
double solution = optimize(f, -2); // helper<decltype(f)> is the default