So there's this code am trying to understand:
#include <iostream>
using namespace std;
int x = -2;
int h(int &x) {
x = 2 * x;
return x;
}
int g(int f) { return x; }
int &f(int &x) {
x += ::x;
return x;
}
int main() {
int x = 6;
f(::x) = h(x);
cout << f(x) << endl;
cout << g(x) << endl;
cout << h(x) << endl;
return 0;
}
Output:
24
12
48
I understood the function of the scope resolution operator (::), which is to use the global int x, but the part that i don't understand is this part: f(::x) = h(x); and this one: int g(int f){return x;}
So what am trying to understand is what happens step by step when these instructions get executed.
The line
f(::x) = h(x);
is equivalent to
operator=(f(::x), h(x));
First, one of the functions f or h are called and the returned value is passed to operator=. Then the other function is called and the returned value is passed to operator=. The order is irrelevant because in either case f changes the value of global x to -4 and returns a reference to it and h changes local x (local in main) to 12 and returns its value. Then the value 12 is assigned to global x.
The line
int g(int f) { return x; }
defines a function that returns the value of global x.
Maybe using different variable names helps understanding:
#include <iostream>
using namespace std;
int globalX = -2;
int h(int &hX) {
hX = 2 * hX;
return hX;
}
int g(int f) { return globalX; } // f is unused
int &f(int &fX) {
fX += ::globalX;
return fX;
}
int main() {
int mainX = 6;
f(::globalX) = h(mainX);
cout << f(mainX) << endl;
cout << g(mainX) << endl;
cout << h(mainX) << endl;
return 0;
}
Related
I have functions Mult, Add, Div, Sub, Mod those takes two integers and returns the result of its parameters. And a function Calc that takes a character as an Operator and returns a pointer to function that returns an integer and takes two integer parameters like Mult.
Functions like Mult's second parameter is default So when I call Calc, Calc returns the address of Mult or Add... depending on the value of parameter of Calc thus I can pass only one argument.
But It doesn't work with pointer to function:
int Add(int x, int y = 2) { // y is default
return x + y;
}
int Mult(int x, int y = 2) { // y is default
return x * y;
}
int Div(int x, int y = 2) { // y is default
return y ? x / y : -1;
}
int Sub(int x, int y = 2) { // y is default
return x - y;
}
int Mod(int x, int y = 2) { // y is default
return y ? x % y : -1;
}
using pFn = int(*)(int, int);
pFn Calc(char c) {
switch (c) {
case '+':
return Add;
case '*':
return Mult;
case '/':
return Div;
case '-':
return Sub;
case '%':
return Mod;
}
return Mult;
}
int main(int argc, char* argv[]){
pFn func = Calc('%');
cout << func(7, 4) << endl; // ok
//cout << func(7) << endl; // error: Too few arguments
cout << Mult(4) << endl; // ok. the second argument is default
func = Calc('/'); // ok
cout << func(75, 12) << endl; // ok
std::cout << std::endl;
}
Above if I call Mult with a single argument it works fine because the second argument is default but calling it through the pointer func it fails. func is pointer to function that takes two integers and returns an int.
Defaulted arguments are a bit of C++ syntactic sugar; when calling the function directly with insufficient arguments, the compiler inserts the default as if the caller had passed it explicitly, so the function is still called with the full complement of arguments (Mult(4) is compiled into the same code as Mult(4, 2) in this case).
The default isn't actually part of the function type though, so you can't use the default for an indirect call; the syntactic sugar breaks down there, since as soon as you are calling through a pointer, the information about the defaults is lost.
For the "why not" I refer you to this answer. If you want to somehow keep the ability to use a default, you need to provide something more than a function pointer, eg a lamdba will do:
auto Double() {
return [](int x,int y=2){ return Mult(x,y); };
}
And by using a variadic lambda (thanks to #Artyer) you do not even have to repeat the default value:
#include <iostream>
int Mult(int x, int y = 2) { // y is default
return x * y;
}
auto Double() {
return [](auto... args) { return Mult(args...); };
}
int main(int argc, char* argv[]){
auto func = Double();
std::cout << func(7, 4) << '\n'; // ok
std::cout << func(7) << '\n'; // ok
std::cout << Mult(4) << '\n'; // ok
}
Live demo
If you always have 2 as default argument, you can wrap your function pointer into a simple helper class like this:
using pFn_ = int(*)(int, int);
class pFn
{
pFn_ ptr;
public:
pFn(pFn_ p) : ptr(p) {}
int operator()(int x, int y = 2) const {
return ptr(x,y);
}
};
Full working example: https://godbolt.org/z/5r7tZ8
This question already has answers here:
What is the 'this' pointer?
(8 answers)
Closed 4 years ago.
I confused what does it mean this pointer and how it is used exactly. in the below examples give the same output. What is the difference putting reference operator(&) in the setX and setY functions?
#include<iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
Test (int x = 0, int y = 0) { this->x = x; this->y = y; }
Test setX(int a) { x = a; return *this; }
Test setY(int b) { y = b; return *this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test obj1;
obj1.setX(10).setY(20);
obj1.print();
return 0;
}
With reference operator
#include<iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
Test (int x = 0, int y = 0) { this->x = x; this->y = y; }
Test &setX(int a) { x = a; return *this; }
Test &setY(int b) { y = b; return *this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test obj1;
obj1.setX(10).setY(20);
obj1.print();
return 0;
}
When you return by value, as in
Test setX(int a) { x = a; return *this; }
then you return a copy of the object. And the copy is totally unrelated to the original object.
When you return a reference, you return a reference to the actual object, no copies are made.
And because of this difference the two programs you show should not produce the same output. The first should say that x is equal to 10 (because you set x on the obj1 object) but then you set y on the copy returned by setX, meaning that obj1.y will still be zero. See e.g. this example.
I have following code and I don't know how can I access the x inside the anonymous namespace in this setting. Please tell me how?
#include <iostream>
int x = 10;
namespace
{
int x = 20;
}
int main(int x, char* y[])
{
{
int x = 30; // most recently defined
std::cout << x << std::endl; // 30, local
std::cout << ::x << std::endl; // 10, global
// how can I access the x inside the anonymous namespace?
}
return 0;
}
You can't!
You cannot access the namespace's members by its name, because it doesn't have one.
It's anonymous.
You can only access those members by virtue of their having been pulled into scope already.
You'll have to access it from a function within the anonymous same scope:
#include <iostream>
int x = 10;
namespace
{
int x = 20;
int X() { return x; }
}
int main(int x, char* y[])
{
{
int x = 30; // most recently defined
std::cout << x << std::endl; // 30, local
std::cout << ::x << std::endl; // 10, global
std::cout << X() << std::endl; // 20, anonymous
// how can I access the x inside the anonymous namespace?
}
return 0;
}
When returning a reference to the object on which the function is invoked, the returned reference can be used to chain function calls on a single object.
Here, I am applying the same concept. But I am getting different output if I initialize objects differently.
First example:
#include<iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
Test(int x = 0, int y = 0) { this->x = x; this->y = y; }
Test &setX(int a) { x = a; return *this; }
Test &setY(int b) { y = b; return *this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test obj1(5, 5);
// Chained function calls. All calls modify the same object
// as the same object is returned by reference
obj1.setX(10).setY(20);
obj1.print();
return 0;
}
Output is 10 and 20, which is correct.
However, output is not correct for the second example:
#include<iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
Test (int x = 0, int y = 0) { this->x = x; this->y = y; }
Test setX(int a) { x = a; return *this; }
Test setY(int b) { y = b; return *this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test obj1;
obj1.setX(10).setY(20);
obj1.print();
return 0;
}
Output is 10 and 0.
Why? I think both are the same, the output of the second program should be 10 and 20 too. What is the reason it's different?
The difference is that the second version of your program returns by value. This means that the second call (i.e. setY) is performed on a copy of obj1, not on the obj1 itself. That's why only X ends up being set, but not Y.
In your first program, on the other hand, the setters return their results as a reference. This means that no copy is being made, so setY is called on the same object as setX, not on its copy.
This question probably only makes sense for people with knowledge on programming languages supporting closures. If you don't, please do not comment "why would you like to do this?": there are tons of legitimate reasons to do that.
It is common in functional languages to define local functions that capture the already defined local variables. In C++, that would look like (but of course is illegal):
#include <iostream>
using namespace std;
int main()
{
int x = 0;
int f() { return x + 1; }
cout << f() << endl; // would print 1
x = 2;
cout << f() << endl; // would print 3
}
To allow this, C++11 introduces lambda functions, so it is actually possible to do it in a rather nice way (though, not as nice as it generally is in functional languages ;-) ):
#include <iostream>
using namespace std;
int main()
{
int x = 0;
auto f = [&] () { return x + 1; };
cout << f() << endl; // actually compiles and prints 1
x = 2;
cout << f() << endl; // actually compiles and prints 3
}
My question is: now that it is possible to automatically capture free variables by reference for functions, wouldn't that be nice to be possible to do for locally defined structs? Ideally, I would love to be able to write:
int main()
{
int x = 0;
struct A
{
int y;
A(int y) : y(y) {}
int f() { return x + y; };
};
A a1(1);
A a2(2);
cout << a1.f() << endl; // would print 1
cout << a2.f() << endl; // would print 2
x = 2;
cout << a1.f() << endl; // would print 3
cout << a2.f() << endl; // would print 4
}
The only workaround I've found is to manually pass as argument to the constructor all the non-local (free) variables, which is a bit of a pain when there are plenty of them:
#include <iostream>
using namespace std;
int main()
{
int x = 0;
struct A
{
// meaningful members
int y;
int f() { return x + y; };
// free variables
int & x;
// Constructor
A(
// meaningful arguments
int y,
// capturing free variables
int & x
) : y(y), x(x) {}
};
A a1(1, x);
A a2(2, x);
cout << a1.f() << endl; // prints 1
cout << a2.f() << endl; // prints 2
x = 2;
cout << a1.f() << endl; // prints 3
cout << a2.f() << endl; // prints 4
}
Do you know of any other workaround that would avoid manually passing as argument all free variables, or do you know if these kind of "environment-aware" locally-defined structs are considered for future extensions of C++? (i.e., C++1y?)
What you ask for is not available, but you can get similar results by combining functions with a combination of lambdas and binders:
auto lambda = [](int i) { return x+i; };
auto a1 = std::bind(lambda,1);
auto a2 = std::bind(lambda,2);
Depending on the amount and shape of changes, you could invert the solution and have a struct that takes the lambda with the capture and then adds it's own logic.
I don't find this particularly beautiful, and I'm not entirely sure it's compliant, but neither g++ nor clang++ complains about this:
#include <iostream>
int main()
{
int x = 1;
auto l = [&](int p){
auto ll0 = [&, p]{ return p + x + 5; };
auto ll1 = [&, p]{ return p + x * 2; };
struct
{
decltype(ll0) l0;
decltype(ll1) l1;
} ret{ll0, ll1};
return ret;
};
std::cout << l(42).l0() << '\n';
auto lo = l(21);
std::cout << lo.l1() << '\n';
}
I think the creation of the unnamed struct could possibly be automated by a macro.
The lambda expressions of C++ are the capturing mechanism and inline object literals of a sort. Depending on your exact purpose, they may be more convenient than a local struct definition.
As a motivating example, consider the following:
// environment
int offset = 42;
struct local_type {
// capture environment 'by-hand'
int offset;
// purpose of the local type is to expose two overloads
int operator()(int x) const
{ return x + offset; }
double operator()(double x) const
{ return x + offset; }
} f { offset };
You can turn this on its head by doing:
int offset = 42;
auto f = make_overload([=](int x) { return offset + x; },
[=](double x) { return offset + x; });
The lambda expressions take care of capturing, the make_overload combinator takes care of building the desired object -- here, one that has an overloaded operator(). (It would be implemented best by making use of inheritance.)
This approach makes sense if you know that you'll (re)use make_overload from various places. For one-time, special uses there's no avoiding writing a specialty type, whether local or not.