如何将双参数函数转换为单参数函数?
在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库的类函数会更好。
在此先感谢!
[增订]
@安迪警车:我想你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
选项。此外,如果它捕获变量(capture-less vs. capturing lambdas),看起来lambda不能被转换为函数指针。所以我认为Andy-Prowl的回答总的来说是这个问题的正确答案,但我需要找到一个不同的解决方法。
选项1:
如果你的成员函数并不暗示对你的类的实例工作(并因此不需要接收this
指针),你可以使它static
:
class SphericalHarmonics
{
...
static double distFunction(Point p);
...
};
double SphericalHarmonics::distFunction(Point p)
{
...
}
现在,您的功能将有效地具有一个参数:
surface(SphericalHarmonics::distFunction);
选项2:
否则,您可以使用讨好成员函数distFunction
和修复其第一,隐含参数(如果您不与C++编译器11的工作,你可以从Boost.Bind库使用等效boost::bind()
):
#include <functional>
SphericalHarmonics *sh = new SphericalHarmonics(1);
auto fxn = std::bind(&SphericalHarmonics::distFunction, sh, _1);
surface(fxn);
OPTION 3:
另外,在C++ 11,一个lambda可以做的工作:
SphericalHarmonics *sh = new SphericalHarmonics(1);
auto fxn = [=] (double d) { return sh->distFunction(d); }
谢谢!我确信这是正确的,所以我已经检查过了。选项1不是一个选项(我想处理特定的类实例)。当我尝试选择2或3时,我得到错误'错误:'fxn'没有命名一个类型'和'错误:'fxn'没有在这个范围内声明。我试过'std :: bind'和'boost :: bind'(包括'
@OwenM:你是否在使用带有-std = C++ 0x或者-std = C++ 11命令行选项的C++ 11编译器? 'auto'关键字需要C++ 11。我也建议你升级到GCC 4.7.2,你使用的版本是相当老的。还有[这个网站](http://www.liveworkspace.org),你可以用不同的编译器编译你的代码。 – 2013-02-28 01:17:20
是的,gcc 4.7.2与-std = C++ 11修复了这个问题! – OwenM 2013-02-28 17:00:51
#include <functional>
SphericalHarmonics *sh = new SphericalHarmonics(1);
surface(std::bind(&SphericalHarmonics::distFunction, sh, _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's answer的std::bind
和lambda表达式会工作得很好:
...
typedef std::function<FT (Point_3)> Function;
typedef CGAL::Implicit_surface_3<GT, Function> Surface_3;
(我还没有真正阅读问题)绑定或拉姆达? – 2013-02-28 00:15:33
这些标签有误导性,应该包含matlab/lambda – Dmitry 2013-02-28 00:25:03
这些解决方案中的任何一个都可以正常工作吗?是不是可以使用bind来代替函数指针? – 2014-09-04 21:36:07