I really want to pass a variable that is auto (function) as input in another function.
Here is a structure that receives parameters for my xroot f:
struct my_f_params {
double flag;
auto inter_auto(double x, double y);
};
Here is the function I essentially want to have (it's based on a GSL library, so the form can't be changed). I want to be able to pass a "function" as a variable, and the only way I guessed it would happen is with auto.
After passing it, I try storing it to a new auto, But I get an error (see below):
double xrootf (double x, void * p)
{
my_f_params * params = (my_f_params *)p;
double flag = (params->flag);
auto inter_auto = (params->inter_auto);
return flag*inter_auto(x);
}
Here is an auto function that returns an auto function. This works perfectly (if xrootf is commented, I can print for example new_f(2)(2), etc):
auto new_f(double x){
auto in_result = [](double x, double y){
return x*y;
};
using namespace std::placeholders;
auto result_f = std::bind(in_result,x,_1);
return result_f;
}
The test code that proves that the auto function new_f is working good:
int main(int argc, char const *argv[])
{
auto nest_f = new_f(-0.5);
printf("%f\n", nest_f(+2));
return 0;
}
Recasting the auto function to double is not working, either (for the struct part of the code).
The error I'm getting is:
auto_pass.cpp: In function 'double xrootf(double, void*)':
auto_pass.cpp:28:42: error: unable to deduce 'auto' from 'params->my_f_params::inter_auto'
28 | auto inter_auto = (params->inter_auto);
| ^
auto_pass.cpp:28:42: note: couldn't deduce template parameter 'auto'
The aim of the code is this:
Have a function that is able to return a function (DONE W/ new_f)
Have a function that is able to take a function as a variable (the one with new_f) (Not Done)
EDIT: Here's a quick Python script that's very easy to achieve what I'm saying:
def new_f(y):
#make any number of computatioanly costly Algebra with y
def g(x):
return x*y
return g
def xroot(f,flag):
return flag-f(flag)
auto is just a placeholder for a compiler-deduced type, depending on the context in which auto is used.
In your example, you can't use auto as the return value of my_f_params::inter_auto(), because the compiler has no way to know what type inter_auto() actually returns, so it can't deduce the type of the auto. You would need to do this instead:
struct my_f_params {
double flag;
auto inter_auto(double x, double y) { return ...; }
};
Then the compiler can deduce the type of the auto from the return statement.
Without that inline code, you would have to be explicit about the return type, eg:
struct my_f_params {
double flag;
double inter_auto(double x, double y);
};
double my_f_params::inter_auto(double x, double y) {
return ...;
}
But in any case, this is not what you really want. Your xrootf() function is trying to call inter_auto() with only one parameter, but my_f_params::inter_auto() is declared to take 2 parameters instead. Based on the Python script you showed, what you really want is for inter_auto to be a reference to some other external function instead. In which case, you can use std::function for that purpose (and there is no need to use std::bind() with a lambda at all).
Try this:
#include <iostream>
#include <functional>
struct my_f_params {
double flag;
std::function<double(double)> inter_auto;
};
double xrootf(double x, void * p)
{
my_f_params * params = static_cast<my_f_params*>(p);
return params->flag * params->inter_auto(x);
}
auto new_f(double x){
return [x](double y) {
return x * y;
};
}
int main(int argc, char const *argv[])
{
my_f_params p;
p.flag = 123.45;
p.inter_auto = new_f(-0.5);
std::cout << xrootf(+2, &p) << std::endl;
return 0;
}
Demo
When calling xrootf(), the resulting equation will be:
flag * (x * y)
which in this example is:
123.45 * (-0.5 * +2) = -123.45
Related
I'm trying to pass function of multiple arguments to other function. I know how to pass a function of single argument function to other function as it was described in C++ primer plus book.
However, I get an error when I'm trying to pass multiple arguments with class(poly_3d) to NR_method function.
#include <iostream>
#define log(x) std::cout<<x<<std::endl;
class constants {
public:
double A;
double B;
double C;
};
double poly_3d(double x, constants cst);
double NR_method(double a, double(*poly_3d)(double));
int main() {
constants cst;
cst.A = 2;
cst.B = -8;
cst.C = 10;
NR_method(3.2, poly_3d);
system("PAUSE");
return 0;
}
double poly_3d(double x, constants cst) {
double y = 3 * cst.A*x*x + 2 * cst.B*x + cst.C;
return y;
}
double NR_method(double a, double (*poly_3d)(double)) {
double c = (*poly_3d)(a);
return c;
}
So the error I'm getting is from NR_method(3.2, poly_3d) in main function. I know that if poly_3d was single arg, this would work.
If this is a horrible way to write codes, then any directions towards learning C++ more effectively for newbies would be much appreciated! Thanks
Take a look at the following code. We're using a template to make things look nicer.
#include <iostream>
#define log(x) std::cout<<x<<std::endl;
class constants {
public:
double A;
double B;
double C;
};
/// Note that we take a ref now, no need to copy cst.
double poly_3d(double x, constants & cst)
{
double y = 3 * cst.A*x*x + 2 * cst.B*x + cst.C;
return y;
}
/// Note that we take a ref now, no need to copy cst.
template <class F>
double NR_method(double a, constants & cst, F func)
{
return func(a, cst);
}
int main() {
constants cst;
cst.A = 2;
cst.B = -8;
cst.C = 10;
NR_method(3.2, cst, &poly_3d);
system("PAUSE");
return 0;
}
You are declaring the function poly_3d with 2 arguments but passing only one. I made a few changes on the code for you
#include <iostream>
#define log(x) std::cout<<x<<std::endl;
class constants {
public:
double A;
double B;
double C;
};
double poly_3d(double x, constants cst);
double NR_method(double a, constants cst, double(*poly_3d)(double, constants));
int main() {
constants cst;
cst.A = 2;
cst.B = -8;
cst.C = 10;
printf("%f", NR_method(3.2, cst, poly_3d));
system("PAUSE");
return 0;
}
double poly_3d(double x, constants cst) {
double y = 3 * cst.A*x*x + 2 * cst.B*x + cst.C;
return y;
}
double NR_method(double a, constants cst, double (*poly)(double, constants)) {
return (*poly)(a, cst);
}
Let's start by simplifying your code. (A minimal example removes distractions, allowing you to better focus on the actual issue.) It looks like you started to do this, but it can be taken further. After removing some stuff that is not needed to reproduce the compile error:
class constants {};
double poly_3d(double x, constants cst);
double NR_method(double a, double(*poly_3d)(double));
int main() {
NR_method(3.2, poly_3d);
}
double poly_3d(double x, constants /*cst*/) {
return 3 * x;
}
double NR_method(double a, double (*poly_3d)(double)) {
return (*poly_3d)(a);
}
Now let's look at the error message:
error: invalid conversion from 'double (*)(double, constants)' to 'double (*)(double)'
This comes with an indication that the conversion is from poly_3d to the second argument of NR_method. If you look at those things, yes, that is the conversion you requested. The argument list for poly_3d is (double, constant), while the declared argument list for the second argument is just (double). There is a mismatch, which makes the conversion invalid. It's not all that different from the single-parameter case: the signatures must match. You can solve this by changing the argument's signature to math that of poly_3d.
Now, if you just make the signatures match, there is another problem in that NR_method does not have a constants value available. That is probably a logical error for you to work out. For a quick workaround to show the elimination of the compiler error, I'll add a local variable.
class constants {
};
double poly_3d(double x, constants cst);
double NR_method(double a, double(*poly_3d)(double, constants)); // <-- Desired signature
int main() {
NR_method(3.2, poly_3d);
}
double poly_3d(double x, constants /*cst*/) {
return 3.0 * x;
}
double NR_method(double a, double (*poly_3d)(double, constants)) {
constants cst; // <-- Allows this to compile, but probably not what you want.
return (*poly_3d)(a, cst); // <-- Needed a second parameter here.
}
There are ways to make this work nicer (for example, a std::function may be more convenient than a function pointer), but explaining those would fall outside the scope of this question, especially since some decisions would depend on the bigger picture.
Using C++, I need to choose a function from a list and then evaluate that function with some inputs. I know just enough to be dangerous, I've solved my problem through some magic, but I have questions regarding my solution. Here is a minimal working example:
double foo(double x) {return x+2;}
double bar(double x) {return x*7;}
double baz(double x) {return x-1;}
int main() {
double x = 3;
auto func_list = {foo,bar,baz};
// This is chosen from an external source,
// setting to a fixed value for the example
int random_choice = 1;
double y = (*(func_list.begin()+random_choice))(x);
return 0;
}
Question: Is this the right way to chose a function from a list and evaluate it? auto here was a double-edged sword, it created something, but I don't know what type it is.
[auto] created something, but I don't know what type it is.
When assigning a braced list (of the same type) to an auto, such as:
auto func_list = {foo,bar,baz};
the list will always convert to a std::initializer_list. That is the type of your auto variable.
Is this the right way?
From there, your remaining code is valid. Whether it's the right way will always be up to you.
To start with,
auto func_list = {foo,bar,baz};
creates a variable of type std::initializer_list<double (*)(double)>. While what you have works, it might be better to use a more expected container:
std::vector<double(*)(double)> func_list = {foo, bar, baz};
Either way, you can write a random_select function like:
template <typenme Iter>
auto random_select(Iter begin, Iter end) -> decltype(*begin)
{
static std::random_device rd;
static std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, std::distance(begin, end) - 1);
return *std::next(begin, dis(gen));
}
template <typename C>
auto random_select(const C& cont) -> decltype(*cont.begin()) {
return random_select(cont.begin(), cont.end());
}
double y = random_select(func_list)(x);
You said,
auto here was a double-edged sword, it created something, but I don't know what type it is.
You can create an array of function pointers and use the array, if that makes it simpler for you. Like:
double foo(double x) {return x+2;}
double bar(double x) {return x*7;}
double baz(double x) {return x-1;}
int main() {
double x = 3;
// Use the compiler to get a type that can be used to define an array.
typedef decltype((&foo)) function_type;
// Define an array of function pointers.
function_type func_list[] = {foo, bar, baz};
// Now use the array to call one of the functions.
int random_choice = 1;
double y = func_list[random_choice](x);
return 0;
}
If you don't wish to use compiler magic, you can use:
int main() {
double x = 3;
// Define a function type using typedef
typedef double (*function_type)(double);
// Define an array of function pointers.
function_type func_list[] = {foo, bar, baz};
// Now use the array to call one of the functions.
int random_choice = 1;
double y = func_list[random_choice](x);
return 0;
}
I am working with gsl to integrate a function. That function is built in a lambda function that has as input a double and a void *, and as output a double.
Now, everything works fine if I use the lambda without any variable capture. But if I do variable capturing, it doesn't work any more.
Could anyone explain me why so?
Here are two snippets of code that I made up to explain my problem:
This one works fine:
int main(int argc, char **argv)
{
double beg = 0;
double end = 10;
auto f = [] (double x, void * p) {return 2.0;};
gsl_integration_workspace * w = gsl_integration_workspace_alloc (GSL_INTEGRATION_WORKSPACE_SIZE);
double result;
double error;
gsl_function F;
F.function = f;
F.params = NULL;
gsl_integration_qags (&F, beg, end, 0, GSL_INTEGRATION_RELATIVE_PRECISION, GSL_INTEGRATION_WORKSPACE_SIZE, w, &result, &error);
cout<<result<<endl;
}
While this one
int main(int argc, char **argv)
{
double beg = 0;
double end = 10;
double p = 2.0;
auto f = [&] (double x, void * p) {return p;};
gsl_integration_workspace * w = gsl_integration_workspace_alloc (GSL_INTEGRATION_WORKSPACE_SIZE);
double result;
double error;
gsl_function F;
F.function = f;
F.params = NULL;
gsl_integration_qags (&F, beg, end, 0, GSL_INTEGRATION_RELATIVE_PRECISION, GSL_INTEGRATION_WORKSPACE_SIZE, w, &result, &error);
cout<<result<<endl;
}
Yields on the line
F.function = f;
the following error:
Assigning to 'double (*)(double, void *)' from incompatible type '<lambda at /[omissis]/main.cpp>'
The answer given by #user657267 is correct. That is why a small wrapper is needed to convert lambas with capture to gsl_function.
Here is the wrapper for the f gsl_function and Here is the wrapper for the fdf gsl_function
You can convert lambda functions to gsl_function after using the wrapper proposed in these two answers in the following way (I haven't invented the version with std::function, it was a well known answer. The template version I haven't seen before my answer).
// std::function version
double a = 1;
gsl_function_pp Fp([=](double x)->double{return a*x;});
gsl_function *F = static_cast<gsl_function*>(&Fp);
//template version
double a = 1;
auto ptr = [=](double x)->double{return a*x;};
gsl_function_pp<decltype(ptr)> Fp(ptr);
gsl_function *F = static_cast<gsl_function*>(&Fp);
Only lambdas without captures can be converted to function pointers.
[expr.prim.lambda]
6 The closure type for a non-generic lambda-expression with no
lambda-capture has a public non-virtual non explicit const conversion
function to pointer to function with C++ language linkage (7.5) having
the same parameter and return types as the closure type’s function
call operator.
Essentially what this means is that
[] (double, void*) {return 2.0;};
acts as though it were defined as
class Lambda
{
public:
double operator()(double, void*);
operator double(*)(double, void*)() const;
};
if the lambda has a capture however the conversion function is not defined, and the lambda cannot be converted to a regular function pointer.
I would like to do something like this:
int main()
{
auto f = [/*some variables*/](/*take lambda function*/)
{/*something with lambda function*/};
f([/*other variables*/](/*variables to be decided by f()*/)
{/*something with variables*/});
}
I know that it is possible to pass a lambda to a function, as well as to a lambda.
The following works:
int main()
{
int x=0;
int y=0;
auto f = [x,y](double (func)(int)) -> double
{func(0); return 0.0;};
f([](int i) -> double
{return 0.0;});
}
But the following does not work (as soon as i change the scope variables to add [x])
int main()
{
int x=0;
int y=0;
auto f = [x,y](double (func)(int)) -> double
{func(0); return 0.0;}
f([x](int i) -> double //[x] does not work
{return 0.0;});
}
which gives the error:
error: function "lambda [](double (*)(int))->double::operator()" cannot be called with the given argument list
argument types are: (lambda [](int)->double)
object type is: lambda [](double (*)(int))->double
would anyone have an idea as to how to fix this, or a way around it?
I am using the intel compiler
icpc (ICC) 13.1.2 with std=c++11
Thanks
There are a couple of things to clarify regarding your question. The first of which is what is a lambda?
A lambda expression is a simple expression from which the compiler will generate a unique type that cannot be named, and at the same time it will generate an instance of the type. When you write: [](int i) { std::cout << i; } the compiler will generate a type for you that is roughly:
struct __lambda_unique_name {
void operator()(int i) const { std::cout << i; }
};
As you can see, it is not a function, but a type that implements operator() as a const member function. If the lambda did any capture, the compiler would generate code to capture the value/references.
As a corner case, for lambdas like the above, where there is no state being captured, the language allows for a conversion from the lambda type to a pointer to function with the signature of the operator() (minus the this part), so the lambda above can be implicitly converted to a pointer to function taking int and returning nothing:
void (*f)(int) = [](int i) { std::cout << i; }
Now that the basics have been stated, in your code you have this lambda:
auto f = [x,y](double (func)(int)) -> double {func(0); return 0.0;};
The rules for parameters to functions (that also apply to lambdas) determine that an argument cannot be of type function, so the argument to the lambda decays to a pointer to function (in the same way that an argument of type array decays to a pointer type):
auto f = [x,y](double (*func)(int)) -> double {func(0); return 0.0;};
At a later point you are trying to pass a lambda that has a capture as an argument. Because there is a capture, the special rule does not apply and the lambda is not convertible to a pointer to function yielding the compiler error that you see.
In the current standard you can go one of two ways. You can use type-erasure to remove the exact type of the callable entity from the signature:
auto f = [x,y](std::function<double(int)> func) -> double {func(0); return 0.0;};
Because a std::function<double(int)> can be initialized with any callable entity with the appropriate signature, this will accept the lambdas in the code below, at the cost of type-erasure that usually implies a dynamic allocation and dynamic dispatch.
Alternatively, you can drop the syntactic sugar and roll the first lambda equivalent manually, but make it generic. In this case, where the lambda is simple this could be a valid option:
struct mylambda {
template <typename F>
double operator()(F fn) const {
fn(0); return 0.0;
}
} f;
// then use the non-lambda as you tried:
f([x](int i) -> double {return 0.0;});
Finally, if you are patient enough, you can wait for C++14, where (most probably, it has not yet been ratified) there will be support for polymorphic lambdas which simplify the creation of the above class:
auto f = [](auto fn) { fn(0.0); return 0.0; } // unrolls to 'mylambda' above
Try using std::function:
#include <functional>
int main()
{
int x=0;
int y=0;
auto f = [x,y](std::function<double(int)> func) -> double
{func(0); return 0.0;};
f([x](int i) -> double {return 0.0;});
}
You may have to simply bite the bullet and implement your own functors like we did in the dark ages:
struct F {
int x;
int y;
F(int x_, int y_) : x(x_), y(y_) {}
template <typename G>
double operator() (G&& g) const {
g(0);
return 0.0;
}
};
#include <iostream>
int main()
{
int x = 0;
int y = 0;
auto f = F(x, y);
f([x](int i){return 0.0;});
f([](int i){std::cout << i << std::endl;});
}
That should keep you going until your compiler supports C++14 generic lambdas.
You could try something like the following if you know the type of the lambda beforehand, for instance:
int main()
{
int x = 0, y = 0;
auto f = [x]( int i )->double {
return (double)x;
};
auto f2 = [x,y]( decltype(f) func )->double {
return func( 0 );
};
f2( f );
return 0;
}
Or alternative you could use the <functional> library for a more generic solution, for instance:
auto f = [x,y]( std::function<double(int)> func ) { /* Do stuff */ };
You can cify a capturing lambda, but this solution has its limitations:
#include <new>
#include <utility>
namespace
{
template <typename F, int I, typename L, typename R, typename ...A>
inline F cify(L&& l, R (*)(A...) noexcept(noexcept(
std::declval<F>()(std::declval<A>()...))))
{
static L l_(std::forward<L>(l));
static bool full;
if (full)
{
l_.~L();
new (static_cast<void*>(&l_)) L(std::forward<L>(l));
}
else
{
full = true;
}
return [](A... args) noexcept(noexcept(
std::declval<F>()(std::forward<A>(args)...))) -> R
{
return l_(std::forward<A>(args)...);
};
}
}
template <typename F, int I = 0, typename L>
inline F cify(L&& l)
{
return cify<F, I>(std::forward<L>(l), F());
}
int main()
{
int x=0;
int y=0;
auto f = [x,y](double (func)(int)) -> double
{func(0); return 0.0;};
f(cify<double(*)(int i)>([x](int i) -> double //works now
{return 0.0;}));
}
Click for a working example.
I have something like the following:
struct A{
virtual int derp(){
if(herp()) return 1;
else return 0;
}
void slurp(){
boost::function<bool(int x, int y)> purp = /** boost bind derp to match lvalue sig **/;
}
}
Any ideas? I want to create the function prup which basically calls derp and ignores the (x,y) passed in.
I need something like
bool purp(int x, int y){ return derp(); }
but want to avoid creating it as a member function, and rather just create it locally if possible?
If C++11 is available, consider using a lambda. Otherwise, you can use Boost.Lambda:
boost::function<bool(int x, int y)> purp = !!boost::lambda::bind(&A::derp, this);
That uses the standard conversion of int to bool.
If you want a specific return value of A::derp to be true, then use ==. For example, suppose you want a return value of 3 to be true:
boost::function<bool(int x, int y)> purp = boost::lambda::bind(&A::derp, this) == 3;
EDIT: Complete example:
#include <iostream>
#include <boost/function.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
struct A {
virtual int derp() {
std::cout << "within A::derp()\n";
return 0;
}
void slurp() {
boost::function<bool(int x, int y)> purp = !!boost::lambda::bind(&A::derp, this);
std::cout << (purp(3, 14) ? "true" : "false") << '\n';
}
};
int main()
{
A a;
a.slurp();
}
Outputs:
within A::derp()
false
boost::function<bool(int x, int y)> purp = boost::bind(&A::derp, this);
This should work as long as derp return value is implicitly convertible to bool. You will get this annoying warning with VC++ though: "warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)"
I am not really sure about the boost::bind library and how to handle your case, but if you have a C++ enabled environment you can use a lambda in place of the bind:
auto purp = [=](int,int) -> bool { return derp(); };
// alternatively:
//std::function<bool(int,int)> purp = [](int,int)->bool{return derp();};
With lambda support suddenly bind does not seem like such a great tool :)
Boolean true/false is just an integer in C implementations already and you could certainly write something to do this. I do not understand the point of doing this or why the function is contained in a struct. The main question is why would you want a function to take parameters so they can be ignored ? Why not have the function return a bool instead of an int ?