无法推断间接调用模板函数的类型

Edw*_*ard 2 c++ templates function

以下代码片段是应该成为优化算法的精简版本:

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);
}
Run Code Online (Sandbox Code Playgroud)

我使用他们试图最小化的函数的模板参数对主函数 ( 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)>&, 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);
Run Code Online (Sandbox Code Playgroud)

(我使用的是 gcc v7.5.0,但我认为这在这里无关紧要。)我想我明白为什么编译器不知道类型line_search(它不查看内部optimize查看如何line_search调用),但是我不知道如何解释正确的类型应该是什么。我希望我能说optimize(f, -2, helper<type of f>),但我没有找到如何做到这一点。我需要对代码进行哪些更改?

顺便说一句,如果有其他同样通用的设计方法,但可以避免模板参数推导问题,我很想了解它们。

Ted*_*gmo 5

您可以添加一个默认类型,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;
}
Run Code Online (Sandbox Code Playgroud)

然后它会在您执行此操作时找到正确的模板实例化

double solution = optimize(f, -2, helper);   // helper is helper<decltype(f)>
Run Code Online (Sandbox Code Playgroud)

如果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;
}
Run Code Online (Sandbox Code Playgroud)

这使得可以在optimize不指定帮助程序的情况下调用:

double solution = optimize(f, -2);   // helper<decltype(f)> is the default
Run Code Online (Sandbox Code Playgroud)