In matlab, one can write:
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++?
I have a library function (from the CGAL library) that expects as an argument a function that itself has only one argument. Ideally, I have a class (SphericalHarmonics
) and I would like to have a member function which takes the one argument. So I have:
FT SphericalHarmonics::distFunction(Point_3 p)
(note that FT
is a type similar to double
) but of course when I try
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.
Note that this can be solved with global variables, i.e.
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.
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.
When, in main
, I use the code:
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 (i.e. surface
required a function pointer argument). This rules out the std::bind
option. Moreover, it appears that a lambda cannot be converted to a function pointer if it captures variables (capture-less vs. capturing lambdas). 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.
OPTION 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
:
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:
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):
#include <functional>
SphericalHarmonics *sh = new SphericalHarmonics(1);
auto fxn = std::bind(&SphericalHarmonics::distFunction, sh, _1);
surface(fxn);
OPTION 3:
Alternatively, in C++11, a lambda could do the job:
SphericalHarmonics *sh = new SphericalHarmonics(1);
auto fxn = [=] (double d) { return sh->distFunction(d); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With