如何将双参数函数"转换"为单参数函数?

Owe*_*enM 5 c c++ matlab lambda function-binding

在matlab中,人们可以写:

S = @(x,y) x^2+y^2-1
G = @(x) S(x,1);
Run Code Online (Sandbox Code Playgroud)

如果我有一个期望单参数函数的函数,我可以做到以上几点.我怎么能用c/c ++做到这一点?

我有一个库函数(来自CGAL库),它希望作为一个参数,一个函数本身只有一个参数.理想情况下,我有一个class(SphericalHarmonics),我希望有一个成员函数,它接受一个参数.所以我有:

FT SphericalHarmonics::distFunction(Point_3 p)
Run Code Online (Sandbox Code Playgroud)

(注意这FT是一个类似的类型double)但当然我尝试的时候

SphericalHarmonics *sh = new SphericalHarmonics(1);
Surface_3 surface(sh->distFunction, Sphere(ORIGIN,2.));
Run Code Online (Sandbox Code Playgroud)

this也被视为参数,我的distFunction函数是一个双参数函数,并抛出一个错误.

请注意,这可以通过全局变量来解决,即

SphericalHarmonics *sh;
FT dist_function(Point_3 p) {
    return sh->distFunction(p);
}

main() {
    sh = new SphericalHarmonics(1);
    Surface_3 surface(dist_function);
}
Run Code Online (Sandbox Code Playgroud)

但是,这真的不理想.我想要一种没有全局变量的方法,因为能够拥有一个可以轻松地与CGAL库集成的类函数会好得多.

提前致谢!

[更新]

@安迪警车:我想你std::bindlambda解决方案,但似乎仍然运行到错误,至于参数的个数.

main我在使用代码时:

SphericalHarmonics *sh = new SphericalHarmonics(cInit, numL, symm);
auto fxn = std::bind(&SphericalHarmonics::distFunction, sh, std::placeholders::_1);
Surface_3 surface(fxn, Sphere_3(ORIGIN,2.));
Run Code Online (Sandbox Code Playgroud)

我得到错误:

~/lib/basisfunctions/SphericalHarmonics2/mesh_an_implicit_function.cpp:62:48: 
error: no matching function for call to     
‘CGAL::Implicit_surface_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, 
double (*)
(CGAL::Point_3<CGAL::Epick>)>::Implicit_surface_3(std::_Bind<std::_Mem_fn
<double (SphericalHarmonics::*)(CGAL::Point_3<CGAL::Epick>)>
(SphericalHarmonics*, std::_Placeholder<1>)>&, Sphere_3)’
Run Code Online (Sandbox Code Playgroud)

~/CGAL-4.1/include/CGAL/Implicit_surface_3.h:50:5: note:   no known conversion 
for argument 1 from ‘std::_Bind<std::_Mem_fn<double (SphericalHarmonics::*)
(CGAL::Point_3<CGAL::Epick>)>(SphericalHarmonics*, std::_Placeholder<1>)>’ to 
‘CGAL::Implicit_surface_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, 
double (*)(CGAL::Point_3<CGAL::Epick>)>::Function 
{aka double (*)(CGAL::Point_3<CGAL::Epick>)}’
Run Code Online (Sandbox Code Playgroud)

~/CGAL-4.1/include/CGAL/Implicit_surface_3.h:34:9: note:   
candidate expects 1 argument, 2 provided
Run Code Online (Sandbox Code Playgroud)

[更新]

现在我很清楚我需要一个可以转换为函数指针的函数(即surface需要一个函数指针参数).这排除了std::bind选项.此外,如果它捕获变量(无捕获与捕获lambda),则看起来lambda不能转换为函数指针.所以我认为下面的Andy-Prowl的答案通常是对这个问题的正确答案,尽管我需要找到一个不同的解决办法.

Dra*_*rax 5

使用std :: bindboost :: bind:

#include <functional>   

SphericalHarmonics *sh = new SphericalHarmonics(1);
surface(std::bind(&SphericalHarmonics::distFunction, sh, _1));
Run Code Online (Sandbox Code Playgroud)


And*_*owl 5

选项1:

如果你的成员函数不隐式地处理你的类的实例(因此不需要接收this指针),你可以做到static:

class SphericalHarmonics
{
    ...
    static double distFunction(Point p);
    ...
};

double SphericalHarmonics::distFunction(Point p)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

现在,您的函数将有效地具有单个参数:

surface(SphericalHarmonics::distFunction);
Run Code Online (Sandbox Code Playgroud)

方案2:

否则,可能会使用std::bind()到咖喱成员函数distFunction和固定其第一,隐含参数(如果不使用C++编译器11的工作,可以使用等效的boost::bind()Boost.Bind库):

#include <functional>

SphericalHarmonics *sh = new SphericalHarmonics(1);
auto fxn = std::bind(&SphericalHarmonics::distFunction, sh, _1);
surface(fxn);
Run Code Online (Sandbox Code Playgroud)

方案3:

或者,在C++ 11中,lambda可以完成这项工作:

SphericalHarmonics *sh = new SphericalHarmonics(1);
auto fxn = [=] (double d) { return sh->distFunction(d); } 
Run Code Online (Sandbox Code Playgroud)