The following uses a simple function pointer, but what if I want to store that function pointer? In that case, what would the variable declaration look like?
#include <iostream>
#include <vector>
using namespace std;
double operation(double (*functocall)(double), double wsum);
double get_unipolar(double);
double get_bipolar(double);
int main()
{
double k = operation(get_bipolar, 2); // how to store get_bipolar?
cout << k;
return 0;
}
double operation(double (*functocall)(double), double wsum)
{
double g = (*functocall)(wsum);
return g;
}
double get_unipolar(double wsum)
{
double threshold = 3;
if (wsum > threshold)
return threshold;
else
return threshold;
}
double get_bipolar(double wsum)
{
double threshold = 4;
if (wsum > threshold)
return threshold;
else
return threshold;
}
You code is almost done already, you just seem to call it improperly, it should be simply
double operation(double (*functocall)(double), double wsum)
{
double g;
g = functocall(wsum);
return g;
}
If you want to have a variable, it's declared in the same way
double (*functocall2)(double) = get_bipolar;
or when already declared
functocall2 = get_bipolar;
gives you a variable called functocall2 which is referencing get_bipolar, calling it by simply doing
functocall2(mydouble);
or passing it to operation by
operation(functocall2, wsum);
You already (almost) have it in your code:
double (*functocall)(double) = &get_bipolar;
This defines a function pointer named functocall which points to get_bipolar.
typedef double (*func_t)(double);
func_t to_be_used = get_bipolar
typedef double (*PtrFunc)(double);
PtrFunc ptrBipolar = get_bipolar;
OR
typedef double (Func)(double);
Func *ptrBipolar = get_bipolar;
which ever you are comfortable to use.
Have a look at boost function, it's a header only library that tidies things up a little (IMHO):
http://www.boost.org/doc/libs/1_42_0/doc/html/function.html
typedef boost::function<double (double)> func_t;
func_t to_be_used = &get_bipolar;
(NB: different syntax required for VC6)
double (*foo)(double);
where foo is the variable name.
You should consider using a typedef:
typedef double (*MyFunc)(double);
MyFunc ptr_func = &get_bipolar;
(*ptr_func)(0.0);
double operation(MyFunc functocall, double wsum)
{
double g;
g = (*functocall)(wsum);
return g;
}
May I recommend also the identity template trick:
template<class T>
class Id
{
typedef T type;
};
Id<double(double)>::type * ptr_func = &get_bipolar;
MyFunc func = &get_bipolar;
(*ptr_func)(0.0);
double operation(Id<double(double)>::type * functocall, double wsum)
{
double g;
g = (*functocall)(wsum);
return g;
}
Related
I'm trying to implement a numerical ODE solver in c++ but I'm having troubles with function pointers (I'm still trying to understand how they works inside classes).
I have a parent class (ODEint) and subclasses in which I will implement different possible algorithms to solve an equation. I pass a function pointer to the parent class (the function represents the equation which is independent of the solver) but I need that function in the child class (different solvers threat that equation in different ways).
When I call the function via pointer in the child class I get the error
odeint.cpp:38:13: error: ‘((Euler*)this)->Euler::.ODEint::field’ cannot be used
as a member pointer, since it is of type ‘pfunc {aka std::vector ()(double)}’
(this->*field)(y);
Here are classes definitions
typedef vector<double> (*pfunc)(double*);
class ODEint {
protected:
double h;
int neq;
double* init_cond;
int nsteps;
string method;
vector<vector<double>> y;
pfunc field;
public:
ODEint(int neq, int nsteps, pfunc);
void setInitCond(double* init_cond);
void solveEq();
virtual vector<double> advance(double h, double *y);
};
class Euler: public ODEint {
public:
Euler(int neq, int nsteps, pfunc, double h);
vector<double> advance(double h, double *y);
};
And here is part of the classes implementation
ODEint::ODEint(int neq, int nsteps, pfunc field){
this->neq = neq;
this->nsteps = nsteps;
this->y.resize(nsteps);
this->field = field;
for (int i = 0; i < nsteps; i++){
this->y[i].resize(neq);
}
}
Euler::Euler(int neq, int nsteps, pfunc field, double h) : ODEint(neq, nsteps, field){
this->h = h;
}
void ODEint::solveEq(){
int n;
cout << "Strarting solver..." << endl;
vector<double> x;
for (n = 0; n < this->nsteps; n++){
x = y[n];
y[n+1] = this->advance(this->h, &x[0]);
}
cout << "Solution termined. Nsteps: " << n << endl;
}
vector<double> Euler::advance(double h, double *y){
vector<double> ynext; ynext.resize(this->neq);
vector<double> f; f.resize(this->neq);
(this->*field)(y); <---------------------------------------------- here is the problem
for (int i = 0; i < this->neq; i++){
ynext[i] = y[i] + h*f[i];
}
}
Finally here is the main
vector<double> field(double *y){
vector<double> vf;
vf[0] = -y[0];
vf[1] = -y[1];
return vf;
}
int main(){
double init_cond[2] = {1.0, 2.0};
const int neq = 1;
Euler prova(neq, (int)1e4, field, 1e-4);
prova.setInitCond(&init_cond[0]);
prova.solveEq();
return 0;
}
I know there may be other problems but I'm still learning c++ and actually the priority is to understand the reason of this error.
Thank you in advance and sorry if the code is a bit confused but as I said previously I'm a kind of beginner.
Your example is a bit large, I didn't use it as-is. But I can spot a fix, with a smaller repro: (I kept your style)
#include <vector>
typedef std::vector<double> (*pfunc)(double*);
class Foo
{
public:
pfunc field;
};
std::vector<double> Bar(double*)
{
return std::vector<double>{};
}
int main()
{
Foo f;
double x;
f.field = &Bar;
(&f)->field(&x);
}
The only meaningful change I needed is to remove the * in front of the call to field().
Now, I will advise not using this pattern at all. The OOP way, IMO would be way cleaner here:
class BaseODE
{
public:
virtual std::vector<double> field(double*) = 0;
// put the rest of the code here.
// when field is called, the Euler version will be called.
};
class Euler:public BaseODE
{
public:
virtual std::vector<double> field(double*) override;
};
Basically, you have no need yet for function pointers, lambdas, std::function or anything complex.
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.
How can i use only 3rd argument (first and second arguments must be default)?
Like this:
double func(const double a = 5, const double b = 6, const double c = 7);
int main()
{
cout << "A = " << func(10) << endl << endl; //if i do like this, i'm using first argument, but not 3rd.
}
C++ doesn't support what you want to do currently. However, there are ways around it. You can use the Named Parameter Idiom or boost's Paremeter library.
I recommend the former. It's clearer, easier to debug, etc...
The only way to do this would be to swap the argument order:
double func(const double c = 7, const double a = 5, const double b = 6);
You could (possibly) use a few wrapper types and overloading, then use the types to name the parameter when calling:
struct A { double a; constexpr static double def = 5.0; };
struct B { double b; constexpr static double def = 6.0; };
struct C { double c; constexpr static double def = 7.0; };
double func(double a=A::def, double b=B::def, double c=C::def) { /* whatever */ }
double func(A a) { return func(a.a, B::def, C::def); }
double func(B b) { return func(A::def, b.b, C::def); }
double func(C c) { return func(A::def, B::def, c.c); }
int main()
{
func(A{3.0});
func(B{9.0});
func(C{12.0});
}
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've created a global function, CallPrice(args). I have a class, EuropeanOption, and I have a class function called CallPrice, which should call the global function using variables from the EuropeanOption class, and return the CallPrice. I'm getting an error, "the global scope has no "CallPrice".
I think this is a common problem. I searched other threads, which said adding :: should solve the problem, but it's not working here for me. Could you identify the cause of the error? Do I need to make this a friend function or some other workaround?
Thanks!
Header:
#ifndef EuropeanOption_HPP
#define EuropeanOption_HPP
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <boost/math/distributions/normal.hpp>
using namespace boost::math;
using namespace std;
namespace CLARK
{
struct EquityParms
{
double T; // years until expiry
double K; // strike price
double sig; // vol
double r; // risk free rate
double b; // cost of carry
};
// Global Call function
const double CallPrice(double T, double K, double sig, double r, double b, double EquityPrice);
class EuropeanOption
{
private:
double T; // years until expiry
double K; // strike price
double sig; // vol
double r; // risk free rate
double b; // cost of carry
double S; // current equity price
double ExactCallPrice;
public:
EuropeanOption(); // default constructor (empty)
EuropeanOption(const EquityParms& data, double EquityPrice); // constructor that sets parms
void copy(const EuropeanOption& source);
~EuropeanOption();
void init(const EquityParms& data, double EquityPrice); // initialize EquityParms
const double CallPrice(); // trying to call global function in this function
};
}
#endif
Source:
#include "EuropeanOption_H.hpp"
namespace CLARK
{
const double CallPrice(double T, double K, double sig, double r, double b, double EquityPrice)
{// Global Function
double temp = sig * sqrt(T);
double d1 = (log(EquityPrice / K) + (r + (sig*sig) * 0.5) * T) / temp;
double d2 = d1 - temp;
normal_distribution<> myNormal(0,1);
return (EquityPrice * cdf(myNormal,d1)) - (K * exp((b - r) * T) * cdf(myNormal, d2));
}
EuropeanOption::EuropeanOption()
{// default constructor
cout << "Default constructor call" << endl;
}
EuropeanOption::EuropeanOption(const EquityParms& data, double EquityPrice)
{// constructor that sets parms
init(data, EquityPrice);
}
void EuropeanOption::copy(const EuropeanOption& source)
{
T = source.T;
K = source.K;
sig = source.sig;
r = source.r;
S = source.S;
b = source.b;
}
EuropeanOption::~EuropeanOption()
{
}
void EuropeanOption::init(const EquityParms& data, double EquityPrice)
{
T = data.T;
K = data.K;
sig = data.sig;
r = data.r;
S = EquityPrice;
b = data.b;
}
const double EuropeanOption::CallPrice()
{ // trying to call global function in this function
return ::CallPrice(T, K, sig, r, b, S); // the global scope has no "CallPrice" ???
}
}
CallPrice is in namespace CLARK. So try
CLARK::CallPrice(/* ... */);
You have declared the global CallPrice in the namespace CLARK. The syntax ::CallPrice tries to use a function CallPrice defined in the global namespace, or an anonymous namespace. Instead, use CLARK::CallPrice.
You are in the namespace CLARK:
return CLARK::CallPrice(T, K, sig, r, b, S);