A default value for a user-defined type

Hi all,

Please consider this snipped-code:

1
2
3
4
5
int main()
{
   cout << int() << endl;
   return 0;
}


This will usually result in showing 0 as the output.

Consider that we have a user-defined type like this:

1
2
3
4
5
6
7
class myvals
{
public:
   myval() { };
   int x = 5;
   double y = 12.5;
};


Now consider a function that receives an int and a double as its arguments:

1
2
3
void foo(int i, double d) {
 cout << "i = " << i <<" and d = " << d << endl;
}


Now how to use the function foo this way:
foo(myvals());

?
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>

void foo( int i, double d ) { std::cout << "::foo: i = " << i << " and d = " << d << '\n' ; }

struct my_vals { int x = 5; double y = 12.5; };

int main() {

    const auto foo = [] ( my_vals mv ) { ::foo( mv.x, mv.y ) ; } ; // hides ::foo

    foo( {} ) ; // ::foo: i = 5 and d = 12.5
    foo( my_vals() ) ; // ::foo: i = 5 and d = 12.5

    foo( {234} ) ; // ::foo: i = 234 and d = 12.5
    foo( my_vals{234} ) ; // ::foo: i = 234 and d = 12.5

    foo( { 567, 8.9 } ) ; // ::foo: i = 567 and d = 8.9
    foo( my_vals{ 567, 8.9 } ) ; // ::foo: i = 567 and d = 8.9
    
    ::foo( 567, 8.9 ) ; // ::foo: i = 567 and d = 8.9 // call foo at (global) namespace scope
}

http://coliru.stacked-crooked.com/a/c6148fffdd3e74bf
Thank you very much.

My intention is using the struct this way:
foo( my_vals() ) ;

In this statement:
const auto foo = [] ( my_vals mv ) { ::foo( mv.x, mv.y ) ; } ; // hides ::foo

The first foo is a new const, but where is it used here?
The statement is not clear for me although I know it's a lambda expression.


Last edited on
> The first foo is a new const, but where is it used here?

Lines 11, 12, 14, 15, 17 and 18. (But not line 20.)
Thanks.
So why do we get errors when we use some other name, say, foot, fo, or anything else in lieu of that!?
If it's our prior function foo, why do we need to declare it this time as a new variable (a const one)?
> So why do we get errors when we use some other name

We can use any valid name for the function object (the closure object)


> If it's our prior function foo ...

It is not our prior function foo; it is a different (local) callable object,
which wraps the call to foo at namespace scope.


We could call it foo_wrapper if we so please:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>

void foo( int i, double d ) { std::cout << "::foo: i = " << i << " and d = " << d << '\n' ; }

struct my_vals { int x = 5; double y = 12.5; };

int main() {

    const auto foo_wrapper = [] ( my_vals mv ) { foo( mv.x, mv.y ) ; } ; 
    
    // call foo through the wrapper
    foo_wrapper( {} ) ; // ::foo: i = 5 and d = 12.5
    foo_wrapper( my_vals() ) ; // ::foo: i = 5 and d = 12.5
    foo_wrapper( {234} ) ; // ::foo: i = 234 and d = 12.5
    foo_wrapper( my_vals{234} ) ; // ::foo: i = 234 and d = 12.5
    foo_wrapper( { 567, 8.9 } ) ; // ::foo: i = 567 and d = 8.9
    foo_wrapper( my_vals{ 567, 8.9 } ) ; // ::foo: i = 567 and d = 8.9

    // call foo directly 
    foo( 567, 8.9 ) ; // ::foo: i = 567 and d = 8.9 
}

http://coliru.stacked-crooked.com/a/a3cee426426367c1
Thanks. you're correct. I hadn't change the name of new foot when using to call it at the time.

Why do you call foo_wrapper an object?
And what's its type? I mean, yes, auto accepts whatever type is returned by the function (here the lambda function/expression) but what's the return type of it here, please?
> Why do you call foo_wrapper an object?

Evaluating a lambda expression yields a copy assignable function object of an unspecified type.

> And what's its type?

The type of this object is formally called a closure type. The properties of the resulting closure type is clearly specified by the standard; however, the precise type is left to the implementation (it is unspecified).
http://eel.is/c++draft/expr.prim.lambda.closure
http://coliru.stacked-crooked.com/a/3f0a730cbf69e922
http://rextester.com/XYUQ97559
Thank you very much.
In this code this time:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
using namespace std;

struct my_vals {
	int x = 5; double y = 12.5; char ch = 'f';
	void set() { x++; y++; ch++; }
};

int main() {
	my_vals m;
	vector<my_vals> vm;

	vm.push_back(my_vals());
	m.set();
	vm.push_back(my_vals());

	for (const auto v : vm)
		cout << v.x << ' ' << v.y << ' ' << v.ch << endl;

	system("pause");
	return 0;
}


Both sets of values added by the vector here are the same! :(

Does vm.push_back(my_vals()); mean pushing back an object of the struct with the class's members in their initial values?
And if so, how to correctly make the new set of values (set by the set member function) added to the vector as we did above.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <vector>

struct my_vals {

	int x = 5; double y = 12.5; char ch = 'f';
	void set() { x++; y++; ch++; }
};

std::ostream& operator<< ( std::ostream& stm, const my_vals& mv ) {

    return stm << "my_vals{ " << mv.x << ", " << mv.y
               << ", '" << mv.ch << "' } @ " << std::addressof(mv) ;
}

int main() {

	my_vals m; // default constructed

	std::vector<my_vals> vec ;

	vec.push_back(my_vals()); // vec now holds a copy of m
	std::cout << "           m == " << m << '\n'
	          << "  vec.back() == " << vec.back() << "\n\n" ;

	m.set(); // modify m (this does not modify the copy in the vector)
	std::cout << "           m == " << m << '\n'
	          << "  vec.back() == " << vec.back() << "\n\n" ;

	vec[0] = { -99, 0.01, '!' }; // modify the value in the vector (this does not modify m)
	std::cout << "           m == " << m << '\n'
	          << "  vec.back() == " << vec.back() << "\n\n" ;
}

http://coliru.stacked-crooked.com/a/a2db1c64d2253861
Yes, I know that, thank you. I meant something else.

Suppose we add a default constructed copy of the struct into the vector:
vec.push_back(my_vals());

Then we modify the values in the struct using the set() function:
m.set();

Now values are changed and we add this new set of values as a new copy of the struct into the vector:
vec.push_back(my_vals());

Now the size of the vector is 2 and it should have two "different" copies of the struct one having the default values (before applying the set() function) and the next having the new values (after applying the set() function). But in practice, both copies are the same!

How to solve this please?

> Then we modify the values in the struct using the set() function: m.set();
> Now values are changed and we add this new set of values as a new copy of the struct into the vector:
> vec.push_back(my_vals());

vec.push_back( my_vals() ); This does *not* add (a copy) of the modified values in m.
vec.push_back(m); This does.
Last edited on
vec.push_back( my_vals() ); This does add (a copy) of the modified values in m.


Did you mean "This does not"?
> Did you mean "This does not"?

Yes. Corrected now. Thanks.
Thank you so much JLBorges. Do you, might I ask, have a linkedIn account please?
> Do you, might I ask, have a linkedIn account please?

No. I do not have any account in any web-based social networking site.
Registered users can post here. Sign in or register to post.