elegant template overloading solution? - c++

In c++11 I have functions
double f(double x1);
double f(double x1, double x2);
double f(double x1, double x2, double x3);
double h(double x);
I also have functions
double g(std::vector<double> y, double x1);
double g(std::vector<double> y, double x1, double x2);
double g(std::vector<double> y, double x1, double x2, double x3);
The implementation of g is something like
double g(std::vector<double> y, double x1, double x2, double x3)
{
double ans = 0.0;
for(g : y)
{
ans = h(g) * f(x1, x2, x3);
}
return ans;
}
Is there an elegant (templated) way of doing this instead of writing g 3 times with overloaded arguments?

template<typename... Ts>
double g(std::vector<double> v, Ts&&...ts ) {
double ret = 1;
for(auto x:v){
ret *= h(x)*f(ts...);
}
return ret;
}
if you want to restrict the ts to be doubles beyond calling f, it needs more work. Otherwise, the above is enough.
(Note the resriction work gets prettier in C++1y with concepts lite: in C++11 I vote to skip the restriction of Ts to doubles, and just rely on f only taking doubles.)

Related

how to pass multiple variables from main function down to other functions C++

I am stuck on this program as follows:
Write a program that takes as input five numbers and outputs the mean (average) and standard deviation of the numbers. If the numbers are x1,x2,x3,x4,x5.
To solve mean : mean = (x1 + x2 + x3 + x4 + x5) / 5;
To solve deviation:
deviation = sqrt((pow(x1 - x, 2) + pow(x2 - x, 2) + pow(x3 - x, 2) + pow(x4 - x, 2) + pow(x5 - x, 2)) / 5);
Your program must contain at least the following functions: a function that calculates and returns the mean and a function that calculates the standard deviation.
I am trying to use variable x1,x2,x3,x4,x5 from main but I am getting unitialized local variable errors and can not compile it.
#include <iostream>
#include <cmath>
using namespace std;
// Named constant definitions (and function declarations):
//Prototype
double meanfn();
double deviationfn();
// Main program:
int main()
{
// Variable declarations:
double x1, x2, x3, x4, x5;
// Function body:
cout << "Enter a number followed by space 5 times to calculate the mean of five numbers. " << endl;
cin >> x1 >> x2 >> x3 >> x4 >> x5;
return 0;
} // end function main
double meanfn()
{
double x1, x2, x3, x4, x5;
double mean;
mean = (x1 + x2 + x3 + x4 + x5) / 5;
return mean;
}// end function meanfn
double deviationfn(double mean)
{
double x,deviation;
double x1, x2, x3, x4, x5;
x = mean;
deviation = sqrt((pow(x1 - x, 2) + pow(x2 - x, 2) + pow(x3 - x, 2) + pow(x4 - x, 2) + pow(x5 - x, 2)) / 5);
return deviation;
}
You have two problems of understanding basics in C++:
Variable scope.
Function parameters.
To briefly explain:
Variables in C++ live only in the scope they were declared in. In your case, you declared: x1, x2, x3, x4, x5 inside of the function main which means they do not exist outside that scope. The variables x1, x2, x3, x4, x5 in meanfn and deviationfn are completely different variables. They only share the same names and that's about it. Therefore, when you declared them inside the functions, they had no previously assigned values which means you cannot use them.
As for function parameters, you have to declare what parameters a function accepts in its signature. Your meanfn signature is double meanfn() which accepts no parameters. If you want it to accept 5 and only 5 double variables, you should change it to accommodate.
There are two solutions based on the explanations above:
#include <iostream>
#include <cmath>
using namespace std;
// Named constant definitions (and function declarations):
//Prototype
double meanfn();
double deviationfn();
// Main program:
// Variable declarations:
double x1, x2, x3, x4, x5; // outside of 'main' making them global and everything has access to these variables.
int main()
{
// Function body:
cout << "Enter a number followed by space 5 times to calculate the mean of five numbers. " << endl;
cin >> x1 >> x2 >> x3 >> x4 >> x5;
// CALL YOUR FUNCTIONS, THEY WONT BE CALLED BY THEIR OWN
double mean = meanfn();
double deviation = deviationfn(mean);
// print results
std::cout << "\n Mean: " << mean << "\n Deviation: " << deviation;
return 0;
} // end function main
double meanfn()
{
double mean = (x1 + x2 + x3 + x4 + x5) / 5;
return mean;
}// end function meanfn
double deviationfn(double mean)
{
double x,deviation;
x = mean;
deviation = sqrt((pow(x1 - x, 2) + pow(x2 - x, 2) + pow(x3 - x, 2) + pow(x4 - x, 2) + pow(x5 - x, 2)) / 5);
return deviation;
}
In the solution above, the variables x1, x2, x3, x4, x5 were moved to be global variables making their access global and hence all functions can use them.
The second solution would consider parameter passing for the functions, such as:
#include <iostream>
#include <cmath>
using namespace std;
// Named constant definitions (and function declarations):
//Prototype
double meanfn(double x1, double x2, double x3, double x4, double x5);
double deviationfn(double mean, double x1, double x2, double x3, double x4, double x5);
// Main program:
int main()
{
// Variable declarations:
double x1, x2, x3, x4, x5;
// Function body:
cout << "Enter a number followed by space 5 times to calculate the mean of five numbers. " << endl;
cin >> x1 >> x2 >> x3 >> x4 >> x5;
// see the difference in the function calls?
double mean = meanfn(x1, x2, x3, x4, x5);
double deviation = deviationfn(mean, x1, x2, x3, x4, x5);
// print results
std::cout << "\n Mean: " << mean << "\n Deviation: " << deviation;
return 0;
} // end function main
double meanfn(double x1, double x2, double x3, double x4, double x5)
{
double mean;
mean = (x1 + x2 + x3 + x4 + x5) / 5;
return mean;
}// end function meanfn
double deviationfn(double mean, double x1, double x2, double x3, double x4, double x5)
{
double x,deviation;
x = mean;
deviation = sqrt((pow(x1 - x, 2) + pow(x2 - x, 2) + pow(x3 - x, 2) + pow(x4 - x, 2) + pow(x5 - x, 2)) / 5);
return deviation;
}
Rather than having 5 variables with numbered names, you can instead have one variable that contains all 5.
#include <iostream>
#include <cmath>
#include <array>
using Values = std::array<double, 5>;
double mean(Values xs)
{
return (xs[0] + xs[1] + xs[2] + xs[3] + xs[4]) / xs.size();
}
double distribution(Values xs, double x_bar)
{
return sqrt((pow(xs[0] - x_bar, 2) + pow(xs[1] - x_bar, 2) + pow(xs[2] - x_bar, 2) + pow(xs[3] - x_bar, 2) + pow(xs[4] - x_bar, 2)) / xs.size());
}
int main()
{
std::cout << "Enter a number followed by space 5 times to calculate the mean of five numbers. " << std::endl;
Values xs;
std::cin >> xs[0] >> xs[1] >> xs[2] >> xs[3] >> xs[4];
auto x_bar = mean(xs);
auto sigma = distribution(xs, x_bar);
std::cout << "\n Mean: " << x_bar << "\n Deviation: " << sigma;
}
But notice that each of those functions is doing the same operation to each of the values, then performing some final calculation based on how many. That can better be expressed using functions from <algorithm>. We then don't need to know how many elements there are.
#include <algorithm>
#include <vector>
using Values = std::vector<double>; // Any number of values
double mean(Values xs)
{
// The default combiner is +
return std::accumulate(xs.begin(), xs.end(), 0) / xs.size();
}
double distribution(Values xs, double x_bar)
{
auto sum_squares = [x_bar](double cumulative, double x){ return cumulative + pow(x - x_bar, 2); }
return sqrt(std::accumulate(xs.begin(), xs.end(), 0, sum_squares) / xs.size());
}

How to pass member functions to composition's member that takes function pointers?

I have the below class that yields this error for the lines I commented: Description Invalid arguments 'Candidates are:
Eigen::Matrix Forward_Euler(double ()(double), double ()(double), double (*)(double))' I'm getting confused when trying to search for a solution.
The signature for Forward Euler is:
Eigen::MatrixXd Forward_Euler(double (*f)(double), double (*gleft)(double), double (*gright)(double))
And my class is:
class C
{
protected:
A x;
B y;
double a;
double b;
Eigen::MatrixXd u;
public:
double f(double x)
{
return a;
}
double gleft(double tau)
{
return b
}
double gright(double tau)
{
return a*b;
}
FD_Euro_Put(): x(), y(), a(0), b(0){}
FD_Euro_Put(char y1, double y2, double y3, double y4, double x2,
double x3, double x4, double x5, double x6, double x7):
x(x1, x2, x3, x4, x5, x6, x7)
{
double Xleft = x1*x2;
double Xright = x1*x3;
double Tauf = x1*x1;
double NN = floor((x1/x2);
a = x1*x2 - 0.5;
b = x1*x2 + 0.5;
pde = HeatPDE(y1, NN, Xleft, Xright, Tauf, Alpha); //begin problem area
u.resize(pde.N+1, pde.M+1);
if(fdtype == 'f')
u = pde.Forward_Euler(&f, &gleft, &gright);
else if(fdtype == 'b')
u = pde.Backward_Euler(&f, &gleft, &gright);
else if(fdtype == 'c')
u = pde.Crank_Nicolson(&f, &gleft, &gright); //end problem area
else
cout << "Incorrect choice for finite difference type!" << endl;
}
Member function pointers and function pointers are not the same thing. Member function pointers have a much more difficult job and need to deal with things like virtual functions and the this pointer.
But look at the functions in your class! They are not really object functions because they use nothing from the object. You can either move them out of the class or make them static functions of the class. If you do either of those things you can use them as function pointers.
I think you have to use a class template and static functions. You can provide the arguments as template arguments.

Acessing protected members of composition class

I have the below class that has two custom objects as member variables. I get errors with the bold section. What is the proper way to access protected members of the composition classes? I get 'within this context' errors the f, gleft, and gright functions and when I try to resize u.
class C
{
protected:
A x;
B y;
double a;
double b;
Eigen::MatrixXd u;
public:
double f(double x)
{
return x;
}
double gleft(double tau)
{
return tau
}
double gright(double tau)
{
return 0;
}
FD_Euro_Put(): x(), y(), a(0), b(0){}
FD_Euro_Put(char y1, double y2, double y3, double y4, double x2,
double x3, double x4, double x5, double x6, double x7):
x(x1, x2, x3, x4, x5, x6, x7)
{
double Xleft = x1*x2;
double Xright = x1*x3;
double Tauf = x1*x1;
double NN = floor((x1/x2);
a = x1*x2 - 0.5;
b = x1*x2 + 0.5;
pde = HeatPDE(y1, NN, Xleft, Xright, Tauf, Alpha); //begin problem area
u.resize(pde.N+1, pde.M+1);
if(fdtype == 'f')
u = pde.Forward_Euler(&f, &gleft, &gright);
else if(fdtype == 'b')
u = pde.Backward_Euler(&f, &gleft, &gright);
else if(fdtype == 'c')
u = pde.Crank_Nicolson(&f, &gleft, &gright); //end problem area
else
cout << "Incorrect choice for finite difference type!" << endl;
}
You can't access protected members of a class unless it explicitly lists you as a friend or you inherit from that class.
A hack would be to wrap that class in your own class which gives getters for those members.
But from a logical standpoint, if those members aren't public, you probably shouldn't need access to them anyway.

Unknown bug affecting Graham's algorithm for finding convex hull

I have programmed the Graham's algorithm but it still gives me the wrong points for the convex hull. I need help. Think I have a bug in my sign function but dunno what it is.
#include <cstdio>
#include <algorithm>
#include <math.h>
#define pb push_back
#define mp make_pair
#include <vector>
using namespace std;
vector <pair<double, double> > st;
pair<double, double> p[1000];
double x, y;
int f(pair <double,double> a, pair<double, double> b)
{
double x1 = x - a.first, x2 = x - b.first;
double y1 = y - a.second, y2 = y - b.second;
return ((x1*y2-y1*x2) < 0);
}
void setlast(double &x1, double &y1, double &x2, double &y2)
{
x2 = st[st.size()-1].first;
y2 = st[st.size()-1].second;
x1 = st[st.size()-2].first;
y1 = st[st.size()-2].second;
}
sign improved I use doubles
double sign(double x1,double y1, double x2,double y2, double y3,double x3)
{
double xx1 = x2 - x1, xx2 = x3 - x1;
double yy1 = y2 - y1, yy2 = y3 - y1;
return (xx1*yy2-yy1*xx2);
}
int main()
{
int n;
x = 0x3f3f3f3f;
y = 0x3f3f3f3f;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%lf %lf", &p[i].first, &p[i].second);
if(p[i].first <= x && p[i].second <= y)
x = p[i].first,
y = p[i].second;
}
sort(p, p + n, f);
p[n].first = x;
p[n].second = y;
st.pb(mp(p[0].first, p[0].second));
st.pb(mp(p[1].first, p[1].second));
double x1, x2, x3, y1, y2, y3;
here I iterate through all vectors and try to determine the points of convex hull
for(int i = 2; i < n; i++)
{
x3 = p[i].first;
y3 = p[i].second;
setlast(x1,y1,x2,y2);
while(1)
if(sign(x1,y1,x2,y2,x3,y3) < 0)
{
st.pb(mp(x3, y3));
break;
}
else
st.pop_back(),
setlast(x1, y1, x2, y2);
}
here printing the convex hull
for(int i = 0; i < st.size(); i++)
printf("%lf %lf\n", st[i].first, st[i].second);
return 0
}
My question, why does int f(pair<int, int>, pair<int, int>) take pair<int, int> instead of pair<double, double>?
Also, why isn't it named something informative like compare_blah?
Lastly, why doesn't it return bool instead of an int? Either works of course, but it will be clearer that this is intended simply as a comparison function if you return a bool. And making your program clear to people who read it should be your primary goal. Getting it to do what it's supposed to is a secondary goal. After all, it doing what it's supposed to is only a transitory state of affairs. Eventually someone will want it to do something else.
The pair<int, int> thing could be your problem right there. You are doing several implicit type conversions in that function between int and double and losing information left and right. I doubt that's what you intended.
If you would use a typedef for your pair like typedef pair<double, double> point2d_t and then use point2d_t everywhere you could protect yourself from mistakes like that and make your program clearer in the bargain.
I'm not familiar enough with Graham's algorithm to evaluate your use of abs inside of f, though it's quite possible the person who commented on this is correct.

Orthogonal variables code duplication problem

I've started refactoring some legacy code recently and came across two functions for drawing a coordinate grid, the problem is that these functions differ only in orthogonal variables they treat, something like that
void DrawScaleX(HDC dc, int step, int x0, int x1, int y0, int y1)
{
for(int x = x0; x < x1; x += step)
{
MoveToEx(dc, x, y0, NULL);
LineTo(dc, x, y1);
}
}
void DrawScaleY(HDC dc, int step, int x0, int x1, int y0, int y1)
{
for(int y = y0; y < y1; y += step)
{
MoveToEx(dc, x0, y, NULL);
LineTo(dc, x1, y);
}
}
So if I decide to add some fancy stuff, like antialiasing or merely change drawing pencil or whatever I'll have to put the same code in both of them and it's code duplication and it's bad we all know why.
My question is how would you rewrite these two functions into a single one to avoid this problem?
Why you just do not extract the body of the for cycle into a separate function? Then you can do the funny stuff in the extracted function.
void DrawScaleX(HDC dc, int step, int x0, int x1, int y0, int y1)
{
for(int x = x0; x < x1; x += step)
{
DrawScale(dc, x, y0, x, y1);
}
}
void DrawScaleY(HDC dc, int step, int x0, int x1, int y0, int y1)
{
for(int y = y0; y < y1; y += step)
{
DrawScale(dc, x0, y, x1, y);
}
}
private void DrawScale(HDC dc, int x0, int y0, int x1, int y1)
{
//Add funny stuff here
MoveToEx(dc, x0, y0, NULL);
LineTo(dc, x1, y1);
//Add funny stuff here
}
Drawing a line is simply joining two points, and drawing a scaling incrementing (x0,y0) and(x1,y1) in a particular direction, through X, and/or through Y.
This boils down to, in the scale case, which direction(s) stepping occurs (maybe both directions for fun).
template< int XIncrement, YIncrement >
struct DrawScale
{
void operator()(HDC dc, int step, int x0, int x1, int y0, int y1)
{
const int deltaX = XIncrement*step;
const int deltaY = YIncrement*step;
const int ymax = y1;
const int xmax = x1;
while( x0 < xmax && y0 < ymax )
{
MoveToEx(dc, x0, y0, NULL);
LineTo(dc, x1, y1);
x0 += deltaX;
x1 += deltaX;
y0 += deltaY;
y1 += deltaY;
}
}
};
typedef DrawScale< 1, 0 > DrawScaleX;
typedef DrawScale< 0, 1 > DrawScaleY;
The template will do its job: at compile time the compiler will remove all the null statements i.e. deltaX or deltaY is 0 regarding which function is called and half of the code goes away in each functor.
You can add you anti-alias, pencil stuff inside this uniq function and get the code properly generated generated by the compiler.
This is cut and paste on steroids ;-)
-- ppi
Here is my own solution
class CoordGenerator
{
public:
CoordGenerator(int _from, int _to, int _step)
:from(_from), to(_to), step(_step), pos(_from){}
virtual POINT GetPoint00() const = 0;
virtual POINT GetPoint01() const = 0;
bool Next()
{
if(pos > step) return false;
pos += step;
}
protected:
int from;
int to;
int step;
int pos;
};
class GenX: public CoordGenerator
{
public:
GenX(int x0, int x1, int step, int _y0, int _y1)
:CoordGenerator(x0, x1, step),y0(_y0), y1(_y1){}
virtual POINT GetPoint00() const
{
const POINT p = {pos, y0};
return p;
}
virtual POINT GetPoint01() const
{
const POINT p = {pos, y1};
return p;
}
private:
int y0;
int y1;
};
class GenY: public CoordGenerator
{
public:
GenY(int y0, int y1, int step, int _x0, int _x1)
:CoordGenerator(y0, y1, step),x0(_x0), x1(_x1){}
virtual POINT GetPoint00() const
{
const POINT p = {x0, pos};
return p;
}
virtual POINT GetPoint01() const
{
const POINT p = {x1, pos};
return p;
}
private:
int x1;
int x0;
};
void DrawScale(HDC dc, CoordGenerator* g)
{
do
{
POINT p = g->GetPoint00();
MoveToEx(dc, p.x, p.y, 0);
p = g->GetPoint01();
LineTo(dc, p.x, p.y);
}while(g->Next());
}
But I it seems to me too complicated for such a tiny problem, so I'm looking forward to still see your solutions.
Well, an obvious "solution" would be to make a single function and add one extra parameter (of enum-like type). And then do an if() or switch() inside, and perform the appropriate actions. Because hey, the functionality of the functions is different, so you have to do those different actions somewhere.
However, this adds runtime complexity (check things at runtime) in a place that could be just better checked at compile time.
I don't understand what's the problem in adding extra parameters in the future in both (or more functions). It goes like this:
add more parameters to all functions
compile your code, it won't compile in a bunch of places because it does not pass new parameters.
fix all places that call those functions by passing new parameters.
profit! :)
If it's C++, of course you could make the function be a template, and instead adding an extra parameter, you add a template parameter, and then specialize template implementations to do different things. But this is just obfuscating the point, in my opinion. Code becomes harder to understand, and the process of extending it with more parameters is still exactly the same:
add extra parameters
compile code, it won't compile in a bunch of places
fix all places that call that function
So you've won nothing, but made code harder to understand. Not a worthy goal, IMO.
I think I'd move:
MoveToEx(dc, x0, y, NULL);
LineTo(dc, x1, y);
into their own function DrawLine(x0,y0,x0,y0), which you can call from each of the existing functions.
Then there's one place to add extra drawing effects?
A little templates... :)
void DrawLine(HDC dc, int x0, int y0, int x0, int x1)
{
// anti-aliasing stuff
MoveToEx(dc, x0, y0, NULL);
LineTo(dc, x1, y1);
}
struct DrawBinderX
{
DrawBinderX(int y0, int y1) : y0_(y0), y1_(y1) {}
void operator()(HDC dc, int i)
{
DrawLine(dc, i, y0_, i, y1_);
}
private:
int y0_;
int y1_;
};
struct DrawBinderY
{
DrawBinderX(int x0, int x1) : x0_(x0), x1_(x1) {}
void operator()(HDC dc, int i)
{
DrawLine(dc, x0_, i, x1_, i);
}
private:
int x0_;
int x1_;
};
template< class Drawer >
void DrawScale(Drawer drawer, HDC dc, int from, int to, int step)
{
for (int i = from; i < to; i += step)
{
drawer(dc, i);
}
}
void DrawScaleX(HDC dc, int step, int x0, int x1, int y0, int y1)
{
DrawBindexX drawer(y0, y1);
DrawScale(drawer, dc, x0, x1, step);
}
void DrawScaleY(HDC dc, int step, int x0, int x1, int y0, int y1)
{
DrawBindexY drawer( x0, x1 );
DrawScale(drawer, dc, y0, y1, step);
}