简体   繁体   English

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

[英]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::bindlambda解决方案,但似乎仍然遇到有关参数数量的错误。

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 :: bindboost :: 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.

相关问题 如何将具有派生参数的函数转换为具有基本参数的函数? - How do I cast a function with a derived argument to a function with a base argument? 用于双参数构造函数的用户定义文字 - User-Defined Literal for Two-Argument Constructor 为私有结构定义两个参数的运算符重载 - Defining two-argument operator overload for private struct 如何转换变量成员以将其作为函数的引用参数传递 - How to cast a variable member to pass it as reference argument of a function 如何显式转换参数以匹配期望的函数参数? - How to explicitly cast argument to match an expected function parameter? 是否适合在函数参数中将字符串文字转换为char *? - Appropriate to cast string literal to char * in function argument? 动态转换为 function 参数类型 (C++) - Dynamically cast to function argument type (C++) 转换因参数类型而异的函数指针 - Cast function pointers that differs by argument type 当单参数构造函数不使用显式关键字时,编译器可以发出警告吗? - Can compiler give warning when no explicit keyword used with one-argument constructor? 从引用元组构造值的元组,使用单参数模板化构造函数 - Constructing tuple of value from tuple of reference, with one-argument templated constructor
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM