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.
Related
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
So I'm a total noob at C++, I decided to learn C++ and skipped directly to the Object-oriented programming. I'm coding a class called KineticEnergy that has a constructor with the parameters x and y which is assigned to the variables mass and velocity.
I have a class method called result() which calculates the Kinetic Energy using its formula. I want to call the parameters from my constructor within the formula but I have no idea what I'm exactly doing here (bad english, don't know how to explain). I am getting errors like "[Error] x was not declared in this scope". Here is the code I written:
#include <iostream>
#include <cmath>
using namespace std;
class KineticEnergy
{
public:
double mass;
double velocity;
KineticEnergy(double x, double y) {
mass = x;
velocity = y;
}
double result()
{
return (1/2) * (x * (pow(y, 2)));
} // What am I gonna do here for this to work?
};
int main()
{
double a = 12.1;
double b = 6.4;
KineticEnergy ke(a, b);
cout << ke.result();
return 0;
}
It is not necessary. your constructor parameters is saved in "mass" and "velocity" as class members.
double result()
{
return (1./2.) * (mass * (pow(velocity , 2.)));
}
Parameters of the parameterized constructor are not member variables. That's why you are storing param values in member variables inside of the parameterized constructor. So that, you should use member variables inside of the result() function.
try this
#include <iostream>
#include <cmath>
using namespace std;
class KineticEnergy
{
public:
double mass;
double velocity;
KineticEnergy(double x, double y) {
mass = x;
velocity = y;
}
double result()
{
return 0.5 * (mass * pow(velocity, 2));
}
};
int main()
{
double a = 12.1;
double b = 6.4;
double Result;
KineticEnergy ke(a, b);
Result = ke.result();
cout << Result;
}
x and y were declared in your constructor, therefore only known by your constructor. you cannot use them outside of it. however, mass and velocity are known variables of your class and can be used anywhere as long as they are public.
in your main you give mass and velocity of your ke object values, that's why you can call any method of your class that uses these variables after(again, as long as they're public)
I'm very new to pointers so please bear with me...
My code defines a function for the multiplication of two matrices (matrixMultiplication). I have then defined a function pointer to this function.
#include <iostream>
void matrixMultiplication (const double A[3][3], const double B[3][3], double output[3][3])
{
int i, j, k;
for (i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
for(k=0;k<3;k++)
{
output[i][j]+=A[i][k]*B[k][j];
}
}
}
}
double (*matrixMultiplication (const double (*left)[3], const double (*right)[3]))[3]
{
double output[3][3];
matrixMultiplication(left, right, output);
}
int main ()
{
using namespace std;
double A[3][3]={{1,1,1},{1,1,1},{1,1,1}};
double B[3][3]={{1,1,1},{1,1,1},{1,1,1}};
cout<<"The function returns..."<<endl;
double print[3][3]=matrixMultiplication(A,B);
int i, j;
for (i=0;i<3;i++)
{
for (j=0;j<3;j++)
{
cout<<print[i][j]<<"\t";
}
cout<<"\n";
}
return 0;
}
What I want to do is output the array given by the pointer function, *matrixMultiplication, using a for loop (just for aesthetic purposes). I have played around with the code and ended up with initialiser or segmentation (11) errors. I feel like I'm missing something blatantly obvious given I'm new to C++...
Any ideas would be most welcome!
The problem is with:
double (*matrixMultiplication (const double (*left)[3], const double (*right)[3]))[3]
{
double output[3][3];
matrixMultiplication(left, right, output);
}
I don't know what it is and neither does my compiler! ;)
Using functional, a matrixMultiplication function type can be defined and used, like so:
#include <functional> // or <tr1/functional>
// type
typedef function<void (const double[3][3], const double[3][3], double[3][3])> MatrixFunction;
// instance
MatrixFunction matrixFunctionPtr(&matrixMultiplication);
// call
matrixFunctionPtr(A,B,print);
Note: you also need to declare your output array double print[3][3]; * before* you call the matrixMultiplication function...
You have a function:
void matrixMultiplication (const double A[3][3], const double B[3][3], double output[3][3])
{
...
}
This function works. It takes three arrays as arguments (which is to say it takes three pointers-- this is a subtle point, and I don't think it's a good exercise for a beginner because it clouds the distinction between passing by value and passing by reference -- but never mind that for now) and returns void (i.e. nothing), and . Now you want to construct a function pointer that points to this function. But this:
double (*matrixMultiplication (const double (*left)[3], const double (*right)[3]))[3]
{
...
}
is not a function pointer; it's a function that returns a pointer to an array of double, but it has some internal errors (and don't even worry about what it takes as arguments for now).
Let's do a simpler example first:
double foo(int n) // function
{
return(3);
}
int main()
{
double (*bar)(int); // function pointer
bar = &foo;
double z = (*bar)(5);
cout << z << endl;
return(0);
}
Now that we see how function pointers work, we apply one to matrixMultiplication:
void (*matFP)(const double A[3][3], const double B[3][3], double output[3][3]);
matFP = &matrixMultiplication;
double C[3][3];
(*matFP)(A,B,C);
I'm facing a big issue which I have been trying to solve in vain for 3 days. I've got a CDS class with a intensity_func member function and a big_gamma member function which is basically the integral of the member intensity_func function.
#include <vector>
#include <cmath>
using namespace std
class CDS
{
public:
CDS();
CDS(double notional, vector<double> pay_times, vector<double> intensity);
~CDS();
double m_notional;
vector<double> m_paytimes;
vector<double> m_intensity;
double intensity_func(double);
double big_gamma(double);
};
And here is the CDS.cpp with the definition of the intensity_func member function :
#include <vector>
#include <random>
#include <cmath>
#include "CDS.h"
double CDS::intensity_func(double t)
{
vector<double> x = this->m_intensity;
vector<double> y = this->m_paytimes;
if(t >= y.back() || t< y.front())
{
return 0;
}
else
{
int d=index_beta(y, t) - 1;
double result = x.at(d) + (x.at(d+1) - x.at(d))*(t - y.at(d))/ (y.at(d+1) - y.at(d));
return result;
}
I have implemented in another source file a function to integrate function and the index_beta function used in the intensity_func member function (using the Simpson's rule). Here is the code:
double simple_integration ( double (*fct)(double),double a, double b)
{
//Compute the integral of a (continuous) function on [a;b]
//Simpson's rule is used
return (b-a)*(fct(a)+fct(b)+4*fct((a+b)/2))/6;
};
double integration(double (*fct)(double),double a, double b, double N)
{
//The integral is computed using the simple_integration function
double sum = 0;
double h = (b-a)/N;
for(double x = a; x<b ; x = x+h) {
sum += simple_integration(fct,x,x+h);
}
return sum;
};
int index_beta(vector<double> x, double tau)
{
// The vector x is sorted in increasing order and tau is a double
if(tau < x.back())
{
vector<double>::iterator it = x.begin();
int n=0;
while (*it < tau)
{
++ it;
++n; // or n++;
}
return n;
}
else
{
return x.size();
}
};
So, what I would like to have in my CDS.cpp to define the big_gamma member function is :
double CDS::big_gamma(double t)
{
return integration(this->intensity, 0, t);
};
But obviously, it does not work and I get the following error message : reference to non static member function must be called. I've then tried to turn the intensity member function into a static function but new problems come out: I can't used this->m_intensity and this->m_paytimes anymore as I get the following error message: Invalid use of this outside a non-static member function.
double (*fct)(double) declares an argument of type "pointer-to-function". You need to declare that as a "pointer-to-member function" instead: double (CDS::*fct)(double). Furthermore, you need an object on which you call the pointer-to-member:
(someObject->*fct)(someDouble);
I'm reading the book by Daoqi Yang "C++ and Object Oriented Numeric Computing for Scientists and Engineers". He has a similar example to what I am showing below, but the exceptions are the class "P" I define and the second to last line (which doesn't work). My question is: why does my compiler generate and error when I supply the function member f.integrand? What can I do to correct this? The errors being generated are C3867, C2440, and C2973.
Here is the code:
class P{
public:
double integrand(double x){
return (exp(-x*x));
}
};
template<double F(double)>
double trapezoidal(double a, double b, int n)
{
double h=(b-a)/n;
double sum=F(a)*0.5;
for(int i=1;i<n;i++)
{
sum+=F(a+i*h);
}
sum+=F(b)*0.5;
return (sum*h);
}
double integrand2(double x){
return (exp(-x*x));
}
int main(){
P f;
cout<< trapezoidal<integrand2>(0,1,100)<<endl; // this works
cout<< trapezoidal<f.integrand>(0,1,100)<<endl; // this doesn't work
}
Template arguments must be compile-time constant expressions or types, and member functions require special handling anyway. Instead of doing this, use boost::function<> as an argument, and boost::bind to create the functor, e.g.
double trapezoidal(double, double, boost::function<double(double)>);
// ...
P f;
trapezoidal(0, 1, 100, integrand2);
trapezoidal(0, 1, 100, boost::bind(&P::integrand, boost::ref(f)));
If you have 0x-capable compiler, you can use std::function and std::bind instead.
Cat Plus Plus is correct - boost::bind is a good way to do this easily. I've also included an alternate solution with the following snippet of code:
class P{
private:
double a;
public:
double integrand(double x){
return (a*exp(-x*x));
}
void setA(double y){
a = y;
}
void getA(){
cout<<a<<endl;
}
struct integrand_caller {
P* p;
integrand_caller(P& aP) : p(&aP) {};
double operator()(double x) const {
return p->integrand(x);
};
};
};
template <typename Evaluator, typename VectorType>
VectorType trapezoidal(Evaluator f, const VectorType& a, const VectorType& b, int n)
{
VectorType h=(b-a)/n;
VectorType sum=f(a)*0.5;
for(int i=1;i<n;i++)
{
sum+=f(a+i*h);
}
sum += f(b)*0.5;
return (sum*h);
}
double integrand2(double x){
return (exp(-x*x));
}
int main(){
P f[5];
for(int i=0;i<5;i++){
f[i].setA(5*i);
f[i].getA();
cout<< trapezoidal(P::integrand_caller(f[i]),(double)0, (double)1, 100) << endl;
cout<<trapezoidal(boost::bind(&P::integrand,f[i],_1), 0.0, 1.0, 100)<<"\n"<<endl;
}
}