5

在matlab中,可以这样写:

S = @(x,y) x^2+y^2-1
G = @(x) S(x,1);

如果我有一个需要单参数函数的函数,我可以执行上述操作。我怎样才能在 C/C++ 中做到这一点?

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

FT SphericalHarmonics::distFunction(Point_3 p)

(请注意,这FT是一种类似于double)但当然当我尝试

SphericalHarmonics *sh = new SphericalHarmonics(1);
Surface_3 surface(sh->distFunction, Sphere(ORIGIN,2.));

this也被当做参数,我的distFunction函数是两个参数的函数,会抛出错误。

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

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

main() {
    sh = new SphericalHarmonics(1);
    Surface_3 surface(dist_function);
}

然而,这真的很不理想。我想要一种没有全局变量的方法,因为能够拥有一个易于与 CGAL 库集成的类函数会好得多。

提前致谢!

[更新]

@Andy-Prowl:我已经尝试过您的std::bind解决lambda方案,但在参数数量方面似乎仍然遇到错误。

当,在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.));

我得到错误:

~/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)’

~/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>)}’

~/CGAL-4.1/include/CGAL/Implicit_surface_3.h:34:9: note:   
candidate expects 1 argument, 2 provided

[更新]

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

4

3 回答 3

5

使用std::bindboost::bind

#include <functional>   

SphericalHarmonics *sh = new SphericalHarmonics(1);
surface(std::bind(&SphericalHarmonics::distFunction, sh, _1));
于 2013-02-28T00:17:59.387 回答
5

选项1:

如果您的成员函数不会隐式地在您的类的实例上工作(因此不需要接收this指针),您可以使它static

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

double SphericalHarmonics::distFunction(Point p)
{
    ...
}

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

surface(SphericalHarmonics::distFunction);

选项 2:

否则,您可以使用std::bind()curry 成员函数distFunction并修复其第一个隐式参数(如果您不使用 C++11 编译器,则可以使用 Boost.Bind 库中的等效boost::bind()

#include <functional>

SphericalHarmonics *sh = new SphericalHarmonics(1);
auto fxn = std::bind(&SphericalHarmonics::distFunction, sh, _1);
surface(fxn);

选项 3:

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

SphericalHarmonics *sh = new SphericalHarmonics(1);
auto fxn = [=] (double d) { return sh->distFunction(d); } 
于 2013-02-28T00:18:19.713 回答
1

在处理 CGAL 的模板化Surface_3类的具体情况下。您可能正在使用这样的东西(来自他们的示例)来定义Surface_3类型:

typedef CGAL::Surface_mesh_default_triangulation_3 Tr;
// c2t3
typedef CGAL::Complex_2_in_triangulation_3<Tr> C2t3;
typedef Tr::Geom_traits GT;
typedef GT::Sphere_3 Sphere_3;
typedef GT::Point_3 Point_3;
typedef GT::FT FT;
typedef FT (*Function)(Point_3);
typedef CGAL::Implicit_surface_3<GT, Function> Surface_3;

这是一种误导,因为它使 CGAL 的等值面类看起来只能处理函数指针(而不是std::function等)。但问题只是我们刚刚这样定义它。只需定义Surface_3用作std::function<FT (Point_3)>其模板参数,Andy Prowl 的答案std::bind中的和 lambda就可以正常工作:

...
typedef std::function<FT (Point_3)> Function;
typedef CGAL::Implicit_surface_3<GT, Function> Surface_3;
于 2014-09-04T22:19:48.423 回答