As a C++ learner, I came across the following piece of code from C++ Language Tutorial and got two questions, could any expert provide some guidance on those?
#include <iostream>
using namespace std;
int addition (int a, int b)
{ return (a+b); }
int subtraction (int a, int b)
{ return (a-b); }
int operation (int x, int y, int
(*functocall)(int,int))
{
int g;
g = (*functocall)(x,y);
return (g);
}
int main () {
int m,n;
int (*minus)(int,int) = subtraction;
m = operation (7, 5, addition);
n = operation (20, m, minus);
cout <<n;
return 0;
}
In function "operation" definition:
Question 1: for "g = (*functocall)(x,y)", does it deference the pointer that points to a function (ex.subtraction) and assign it to g?
Question 2: for "return(g)", I'm wondering why we put parenthesis for g?
And for "int (*minus)(int,int) = subtraction;" in the main function, is that okay if we write the following instead?
int (*minus)(int,int)
minus = subtraction
Question 1: for g = (*functocall)(x,y), does it deference the
pointer that points to a function (ex.subtraction) and assign it to g?
Answer: No.
(*functocall)(x,y);
is simply one allowable syntax for invoking the function from the pointer passed as a parameter. It is entirely equivalent to:
functocall(x,y);
Which simply eliminates the (*...) syntax which is allowable but unnecessary.
Question 2: for return(g), I'm wondering why we put parenthesis for
g?
The parenthesis too are discretionary and are superfluous to the return. Simply providing:
return g;
is all that is needed as there is no expression requiring evaluation priority provided by the enclosing (..).
Before I start, your code uses way more parenthesis than it needs.
Here is the same code, better formatted and reduced:
#include <iostream>
using namespace std;
int addition (int a, int b)
{ return a+b; }
int subtraction (int a, int b)
{ return a-b; }
int operation (int x, int y, int (*functocall)(int,int))
{
int g;
g = functocall(x,y);
return g;
}
int main () {
int m,n;
int (*minus)(int,int) = subtraction;
m = operation (7, 5, addition);
n = operation (20, m, minus);
cout <<n<<"\n";
return 0;
}
for "g = (*functocall)(x,y)", does it deference the pointer that points to a function (ex.subtraction) and assign it to g?
In a nutshell - yes. When calling a function through it's pointer, it is not necessary to explicitly dereference it. I know, it's surprising and counter to the way pointers are typically used.
Think of it this way. Whenever you are just writing the name of a function, you are essentially getting the function's pointer. This is why you wrote as you did, rather than write:
m = operation (7, 5, &addition);
You do not need to explicitly dereference when using a function pointer for the same reason you do not need to explicitly use the address of operator when taking its address in the first place.
Question 2: for "return(g)", I'm wondering why we put parenthesis for g?
There is positively no good reason to. In fact, there is no reason to do it for any of your return statements.
And for "int (*minus)(int,int) = subtraction;" in the main function,
is that okay if we write the following instead?
int (*minus)(int,int);
minus = subtraction;
Personally, I recommend you use:
int (*minus)(int,int) = nullptr;
minus = subtraction;
so as not to leave uninitialized variables, but otherwise, yes, absolutely. A pointer to function variable is just like any other variable.
Related
I just started C++ and I don't understand why Max cannot be used as a function in this case.
What I'm trying to do in this code is find the maximum number between the first one and the forth one, on any random number that only has 4 digits.
I've tried inserting Max to int, also to cin but it still does not work. any ideas on how to do it?
Thank you!
#include <iostream>
using namespace std;
int main()
{
int Max, a, b, c, d;
cin>>Max>>a>>b>>c>>d;
Max(a,b) = (a+b+abs(a-b))/2;
Max(b,c) = (b+c+abs(b-c))/2;
Max(c,d) = (c+d+abs(c-d))/2;
Max = (Max(a,b)+Max(b,c)+Max(c,d)+abs(Max(a,b)-Max(b,c)-Max(c,d)))/2;
}
There is some confusion, you'll need to study function syntaxes.
A variable declaration:
int Max;
The above declares a variable called Max.
A function declaration:
int Max(int a, int b);
The above declares a function, Max, which takes 2 int parameters: a and b.
A function definition could be:
int Max(int a, int b)
{
if (a > b)
{
return a;
}
return b;
}
For extra points, find the calculus formula for return the maximum value of 2 integers. :-)
Notes:
1. The above function can't be on the Left-Hand Side (LHS) of an assignment operation (it doesn't make sense, how would the function be assigned a value?).
2. The function returns a value. You should assign the value to a variable or print it:
int maximum = Max(3,15);
std::cout << "Maximum of 4, 24 is: " << Max(24,4) << "\n";
I am a beginner in C++ and want to do simple example of composite function.
For example, in MATLAB, I can write
a = #(x) 2*x
b = #(y) 3*y
a(b(1))
Answer is 6
I searched following questions.
function composition in C++ / C++11 and
Function Composition in C++
But they are created using advanced features, such as templates, to which I am not much familiar at this time. Is there a simple and more direct way to achieve this? In above MATLAB code, user does not need to know implementation of function handles. User can just use proper syntax to get result. Is there such way in C++?
** Another Edit:**
In above code, I am putting a value at the end. However, if I want to pass the result to a third function, MATLAB can still consider it as a function. But, how to do this in C++?
For example, in addition to above code, consider this code:
c = #(p,q) a(p)* b(q) %This results a function
c(1,2)
answer=12
d = #(r) a(b(r))
d(1)
answer=6
function [ output1 ] = f1( arg1 )
val = 2.0;
output1 = feval(arg1,val)
end
f1(d)
answer = 12
In this code, c takes two functions as input and d is composite function. In the next example, function f1 takes a function as argument and use MATLAB builtin function feval to evaluate the function at val.
How can I achieve this in C++?
How about:
#include <iostream>
int main(int, char**)
{
auto a = [](int x) { return 2 * x; };
auto b = [](int y) { return 3 * y; };
for (int i = 0; i < 5; ++i)
std::cout << i << " -> " << a(b(i)) << std::endl;
return 0;
}
Perhaps I'm misunderstanding your question, but it sounds easy:
int a(const int x) { return x * 2; }
int b(const int y) { return y * 3; }
std::cout << a(b(1)) << std::endl;
Regarding your latest edit, you can make a function return a result of another function:
int fun1(const int c) { return a(c); }
std::cout << fun1(1) << std::endl;
Note that this returns a number, the result of calling a, not the function a itself. Sure, you can return a pointer to that function, but then the syntax would be different: you'd have to write something like fun1()(1), which is rather ugly and complicated.
C++'s evaluation strategy for function arguments is always "eager" and usually "by value". The short version of what that means is, a composed function call sequence such as
x = a(b(c(1)));
is exactly the same as
{
auto t0 = c(1);
auto t1 = b(t0);
x = a(t1);
}
(auto t0 means "give t0 whatever type is most appropriate"; it is a relatively new feature and may not work in your C++ compiler. The curly braces indicate that the temporary variables t0 and t1 are destroyed after the assignment to x.)
I bring this up because you keep talking about functions "taking functions as input". There are programming languages, such as R, where writing a(b(1)) would pass the expression b(1) to a, and only actually call b when a asked for the expression to be evaluated. I thought MATLAB was not like that, but I could be wrong. Regardless, C++ is definitely not like that. In C++, a(b(1)) first evaluates b(1) and then passes the result of that evaluation to a; a has no way of finding out that the result came from a call to b. The only case in C++ that is correctly described as "a function taking another function as input" would correspond to your example using feval.
Now: The most direct translation of the MATLAB code you've shown is
#include <stdio.h>
static double a(double x) { return 2*x; }
static double b(double y) { return 3*y; }
static double c(double p, double q) { return a(p) * b(q); }
static double d(double r) { return a(b(r)); }
static double f1(double (*arg1)(double))
{ return arg1(2.0); }
int main()
{
printf("%g\n", a(b(1))); // prints 6
printf("%g\n", c(1,2)); // prints 12
printf("%g\n", d(1)); // prints 6
printf("%g\n", f1(d)); // prints 12
printf("%g\n", f1(a)); // prints 4
return 0;
}
(C++ has no need for explicit syntax like feval, because the typed parameter declaration, double (*arg1)(double) tells the compiler that arg1(2.0) is valid. In older code you may see (*arg1)(2.0) but that's not required, and I think it makes the code less readable.)
(I have used printf in this code, instead of C++'s iostreams, partly because I personally think printf is much more ergonomic than iostreams, and partly because that makes this program also a valid C program with the same semantics. That may be useful, for instance, if the reason you are learning C++ is because you want to write MATLAB extensions, which, the last time I checked, was actually easier if you stuck to plain C.)
There are significant differences; for instance, the MATLAB functions accept vectors, whereas these C++ functions only take single values; if I'd wanted b to call c I would have had to swap them or write a "forward declaration" of c above b; and in C++, (with a few exceptions that you don't need to worry about right now,) all your code has to be inside one function or another. Learning these differences is part of learning C++, but you don't need to confuse yourself with templates and lambdas and classes and so on just yet. Stick to free functions with fixed type signatures at first.
Finally, I would be remiss if I didn't mention that in
static double c(double p, double q) { return a(p) * b(q); }
the calls to a and b might happen in either order. There is talk of changing this but it has not happened yet.
int a(const int x){return x * 2;}
int b(const int x){return x * 3;}
int fun1(const int x){return a(x);}
std::cout << fun1(1) << std::endl; //returns 2
This is basic compile-time composition. If you wanted runtime composition, things get a tad more involved.
I was trying to generate an error in swap code in C++. Interestingly, instead of an error, it successfully shows the opposite. My code look like this:
#include<iostream>
using namespace std;
void swap(int *x, int *y)
{
int *tmp = x;
x = y;
y = tmp;
}
int main()
{
int u = 10;
int v = 20;
int * p = &u;
int * q = &v;
swap(*p, *q);
std::cout<<"u :-"<<u<<" v :-"<<v<<endl;
return 0;
}
The value of u and v got swapped. In this, I am passing pointer value instead of reference but the value gets swapped, How?
Exact code can be found at:
https://ideone.com/kMJHL6
swap(*p, *q);
Since the type of *p and *q are not int *, (it's just int) this code doesn't call your swap function. Instead, it calls the function std::swap, which is in standard C++ library, by function overloading resolving.
Your code has using namespace std; - your case is one of examples that show why you shouldn`t use it.
I think that you're calling the swap function of algorithm library, and not your function
Here's the code:
#include<iostream>
using namespace std;
typedef struct ptrs
{
int (*addptr)(int a, int b);
}mems;
int add(int a, int b)
{
int result = a+b;
return result;
}
int main()
{
mems ptrtest;
ptrtest.addptr = &add;
int c = (*ptrtest.addptr)(3,4);
//int c = ptrtest.addptr(3,4);
cout << c << endl;
return 0;
}
if I replace the code int c = (*ptrtest.addptr)(3,4); with it's next line(annotated now), the result will be the same, why is that?
Of course, int c = (*ptrtest.addptr)(3,4); is the base case. However, in C++ (and in C as well), if you use the call (()) operator on a function pointer, it will do the "dereferencing" automatically. Just like when assigned to a variable of function pointer type, the name of a function decays into a function pointer, i. e.
int (*fptr)() = some_func;
is just as valid as
int (*fptr)() = &some_func;
albeit the type of func is int ()(void).
Functions and function pointers can be used interchangeably, presumably for convenience. In particular, section 5.2.2 of the C++11 standard specifies that a function call can occur using a function or a pointer to a function.
C++ will automatically cast a function name to a function pointer (and vise versa) if doing so will create correct syntax.
I copied this program from a c++ practice book. What's going on behind the scenes?
The expected output is:
sum=30 sum=70
#include<iostream>
using namespace std;
class M
{
int x;
int y;
public:
void set_xy(int a, int b)
{
x=a;
y=b;
}
friend int sum(M m);
};
int sum (M m);
//so far so good, problem begins from here. what's happening after here?
{
int M ::*px = &M ::x;
int M ::*py = &M ::y;
M *pm =&m;
int s= m.*px+ pm->*py;
return s;
}
int main()
{
M n;
void (M :: *pf)(int, int) = &M ::set_xy;
(n.*pf)(10, 20);
cout <<"sum=" << sum(n) << endl;
M *op= &n;
(op-> *pf)(30,40);
cout << "sum=" << sum(n)<< endl;
cin.ignore();
getchar();
return 0;
}
The problem is because of extra whitespace at op-> *pf:
(op->*pf)(30,40); // ok
I think #fefe has probably said the reason in comment. ->* is a single operator, similar to .*. So, if those 2 are separated, then it will result in different syntax, which gives compiler error.
Take a look at Pointer to class data. And for the error, ->* is an operator, you can't put a space between them.
iammilind bet me to the error; op-> *pf must be changed so that you have ->* together as a single operator - a pointer to member operator (couldn't find a better link). The whitespace in op ->* pf is perfectly valid.
That's the same for something like i++; ++ is a single operator and will cause an error if you try and have i+ +.
Now for what it's doing. The example is of a pointer to a member function. pf is being declared as a member function of class M, that takes two int arguments with a void return type. It's being initialized to point to the M::set_xy function.
Inside main:
n is of type M, therefore in order to use pf to call set_xy of n you'd use the .* operator: (n.*pf)(10, 20);. That's equivalent to n.set_xy(10, 20);.
Since op is of type M* (a pointer to an M object), you'll need to use the ->* operator and call the function pointed to by pf as: (op->*pf)(30, 40);, which is equivalent to op->set_xy(30, 40);
Inside sum:
The examples are simply of pointers to member/instance variables, as opposed to member functions. It's simply demonstrating how you would add together m.x and m.y using those types of pointers.