[英]How to “cast” a two-argument function into a one-argument function?
In matlab, one can write: 在matlab中,人们可以写:
S = @(x,y) x^2+y^2-1
G = @(x) S(x,1);
If I have a function expecting a one-argument function, I can do the above. 如果我有一个期望单参数函数的函数,我可以做到以上几点。 How can I do this in c/c++?
我怎么能用c / c ++做到这一点?
I have a library function (from the CGAL library) that expects as an argument a function that itself has only one argument. 我有一个库函数(来自CGAL库),它希望作为一个参数,一个函数本身只有一个参数。 Ideally, I have a class (
SphericalHarmonics
) and I would like to have a member function which takes the one argument. 理想情况下,我有一个类(
SphericalHarmonics
),我希望有一个成员函数,它接受一个参数。 So I have: 所以我有:
FT SphericalHarmonics::distFunction(Point_3 p)
(note that FT
is a type similar to double
) but of course when I try (请注意,
FT
是类似于double
的类型)但当然我尝试的时候
SphericalHarmonics *sh = new SphericalHarmonics(1);
Surface_3 surface(sh->distFunction, Sphere(ORIGIN,2.));
this
is also treated as an argument, my distFunction
function is a two-argument function, and an error is thrown. this
也被视为参数,我的distFunction
函数是一个双参数函数,并抛出一个错误。
Note that this can be solved with global variables, ie 请注意,这可以通过全局变量来解决,即
SphericalHarmonics *sh;
FT dist_function(Point_3 p) {
return sh->distFunction(p);
}
main() {
sh = new SphericalHarmonics(1);
Surface_3 surface(dist_function);
}
However, this is really non-ideal. 但是,这真的不理想。 I'd like a way to do this without global variables, as it would be far better to be able to have a class function that easily integrates with the CGAL library.
我想要一种没有全局变量的方法,因为能够拥有一个可以轻松地与CGAL库集成的类函数会好得多。
Thanks in advance! 提前致谢!
[UPDATED] [更新]
@Andy-Prowl: I have tried your std::bind
and lambda
solutions, but still seem to be running into errors with regards to the number of arguments. @ Andy-Prowl:我已经尝试了你的
std::bind
和lambda
解决方案,但似乎仍然遇到有关参数数量的错误。
When, in main
, I use the code: 在
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.));
I get the errors: 我得到错误:
~/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)’
and 和
~/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>)}’
and 和
~/CGAL-4.1/include/CGAL/Implicit_surface_3.h:34:9: note:
candidate expects 1 argument, 2 provided
[UPDATED] [更新]
It is now clear to me that I need a function which can be converted to a function pointer (ie surface
required a function pointer argument). 现在我很清楚我需要一个可以转换为函数指针的函数(即
surface
需要一个函数指针参数)。 This rules out the std::bind
option. 这排除了
std::bind
选项。 Moreover, it appears that a lambda cannot be converted to a function pointer if it captures variables ( capture-less vs. capturing lambdas ). 此外,如果它捕获变量(无捕获与捕获lambda ),则看起来lambda不能转换为函数指针。 So I think Andy-Prowl's answer below is in general the correct answer to this question, although I'll need to find a different work-around.
所以我认为下面的Andy-Prowl的答案通常是对这个问题的正确答案,尽管我需要找到一个不同的解决办法。
Use std::bind or boost::bind : 使用std :: bind或boost :: bind :
#include <functional>
SphericalHarmonics *sh = new SphericalHarmonics(1);
surface(std::bind(&SphericalHarmonics::distFunction, sh, _1));
OPTION 1: 选项1:
In case your member function does not to implicitly work on an instance of your class (and therefore does not need to receive a this
pointer), you can make it static
: 如果您的成员函数不隐式地处理您的类的实例(因此不需要接收
this
指针),您可以将其设置为static
:
class SphericalHarmonics
{
...
static double distFunction(Point p);
...
};
double SphericalHarmonics::distFunction(Point p)
{
...
}
Now, your function will effectively have a single argument: 现在,您的函数将有效地具有单个参数:
surface(SphericalHarmonics::distFunction);
OPTION 2: 方案2:
Otherwise, you may use std::bind()
to curry the member function distFunction
and fix its first, implicit argument (if you are not working with a C++11 compiler, you can use the equivalent boost::bind()
from the Boost.Bind library): 否则,您可以使用
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);
OPTION 3: 方案3:
Alternatively, in C++11, a lambda could do the job: 或者,在C ++ 11中,lambda可以完成这项工作:
SphericalHarmonics *sh = new SphericalHarmonics(1);
auto fxn = [=] (double d) { return sh->distFunction(d); }
In the specific case of dealing with CGAL's templated Surface_3
class. 在处理CGAL的模板化
Surface_3
类的特定情况下。 You're probably using something like this (from their example) to define Surface_3
type: 您可能正在使用类似的东西(来自他们的示例)来定义
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;
This is misleading because it makes it seem like CGAL's isosurface classes can only deal with function pointers (as opposed to std::function
etc.). 这是误导性的,因为它看起来像CGAL的isosurface类只能处理函数指针(而不是
std::function
等)。 But the problem is only that we've just defined it that way . 但问题只是我们刚才那样定义它 。 Simply define
Surface_3
to use std::function<FT (Point_3)>
as its template argument and the std::bind
and lambdas from Andy Prowl's answer will work just fine: 只需将
Surface_3
定义为使用std::function<FT (Point_3)>
作为模板参数, Andy Prowl的答案中的std::bind
和lambdas就可以正常工作:
...
typedef std::function<FT (Point_3)> Function;
typedef CGAL::Implicit_surface_3<GT, Function> Surface_3;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.