How to copy members with same names in different Structures? - c++

I have two different structures. Both have some members of same type & name.
How can I copy all those matching members all at once?
struct a{ int i, int j};
struct b{ int j, int k};
I wanna perform a=b, kind of operation, where b.j get copied into a.j.
Like wise, how any such matching members should get copied?

Just make an assignment operator, and copy everything you want there
struct a{ int i; int j; };
struct b{
void operator=(const a & other)
{
j = other.j;
}
int j;
int k;
};
Then you can just write
a one;
b two;
two = one;

Since there is some set of matching members of the same type maybe the solution is to pack them together to common type.
struct c{ int i, int j};
struct a{ c common, int k, int l, ..., double u};
struct b{ c common, int a, int b, ..., float u, int v};
a one;
b two;
one.common = two.common;
If it is impossible because you cannot change the code this way, then I would suggest to write some copy function, but not assignment operator because some time later you or someone else may and probably will use that assignment incorrectly, thinking that it copies all members.
void copySharedMembersOfAB( a&, a const& b)
{
a.i = b.i;
a.j = b.j;
}

Related

Initialize parameter into constructor, other than the first one

I want to explicitly change the second parameter in a constructor of a struct, in the following scenario. Is it possible, if so, how?
struct foo{
int x;
int y;
foo(int a=4, int b=6){
x=a;
y=b;
}
};
int main(){
foo *f = new foo();
cout<<f->x<<" "<<f->y<<endl;
//4 6
foo *g = new foo(3,4);
cout<<g->x<<" "<<g->y<<endl;
//3 4
foo *h = new foo(3);
cout<<h->x<<" "<<h->y<<endl;
//3 6
//Can something like this be
//done in C++, if I want
//to change the value of the
//second variable only
foo *k = new foo(b = 13);
return 0;
}
Is it possible, if so, how?
It is not possible with constructor. In general, c++ does not support named keyword arguments to functions, and it is not possible to skip arguments even if they have a default, if you want to pass a non-default after it.
It will be possible without constructor using list initialisation syntax since C++20 using designated initialisers, if you use default member initialisers:
struct foo{
int x = 4;
int y = 6;
};
int main(){
foo f {.y = 4};
}
You can achieve something similar with tag dispatching; No need for future standard:
struct foo{
int x = 4;
int y = 6;
enum Xtag { Xinit };
enum Ytag { Yinit };
foo(int a, int b) : x(a), y(b) {}
foo(Xtag, int a) : x(a) {}
foo(Ytag, int b) : y(b) {}
};
int main(){
foo f(foo::Yinit, 4);
}
A solution using lambda that can be used without modifying an existing class. Following works with your definition of foo:
auto make_foo_x4 = [](int b) {
return foo(4, b);
};
foo f = make_foo_y(4);
The downside is that we have to explicitly repeat the default value of x, so this can break assumptions if the default is changed in class definition.

Marking a member variable to not copy

I have a class that contains POD members. I need to have all members copied, except one (member a in the example case). The way I'm doing it right now is as follows:
class Example
{
private:
int a = 0;
int b = 0;
int c = 0;
int d = 0;
double e = 0;
public:
Example& operator=(const Example &rhs)
{
b = rhs.b;
c = rhs.c;
d = rhs.d;
e = rhs.e;
return *this;
}
Example() {};
Example(const Example& toCopy)
{
*this = toCopy;
}
};
Is there a way to mark the variable to not copy, as doing it this way is verbose and prone to bugs if I later modify this class?
You can wrap the "odd man out", a, in a struct and define that structs behavior separately:
class Example
{
private:
CopyLess a;
int b = 0;
int c = 0;
int d = 0;
double e = 0;
struct CopyLess {
int a = 0;
CopyLess& operator=(const CopyLess&) { return *this; }
CopyLess(const CopyLess&) {}
};
};
Note that I didn't bother writing any special members for Example anymore because the defaults do what you want. Writing code this way to avoid writing special members as much as possible is called the "Rule of Zero", more information and examples: http://www.nirfriedman.com/2015/06/27/cpp-rule-of-zero/.
No, you cannot make the implicit copy assignment skip members. Defining a custom assignment operator as you have done is the way to achieve your desired behaviour.
Doing it this way is verbose and prone to bugs if I later modify this class
You can group the copied members into a single subobject. That way the custom copy assignment is not fragile to changes and verbosity remains constant in relation to number of copied members.
Bonus: You don't need to specify value initialization for the members separately, but one for the entire subobject is enough.
class Example
{
int a = 0;
struct {
int b;
int c;
int d;
double e;
} state = {};
public:
Example& operator=(const Example &rhs)
{
state = rhs.state;
return *this;
}
...
Since the members are private this won't change the existing API of the class.

Pushing back an object in a vector without the object

I know that the correct way of push back an object in a vector is to declare an object of the same class and pass it by value as argument of method push_back. i.e. something like
class MyClass{
int a;
int b;
int c;
};
int main(){
std::vector<MyClass> myvector;
MyClass myobject;
myobject.a = 1;
myobject.b = 2;
myobject.c = 3;
myvector.push_back(myobject);
return 0;
}
My question is: it's possible to push back an object passing only the values of the object and not another object? i.e. something like
class MyClass{
int a;
int b;
int c;
};
int main(){
std::vector<MyClass> myvector;
int a = 1;
int b = 2;
int c = 3;
myvector.push_back({a, b, c});
return 0;
}
If you declare a, b, c as public,
class MyClass{
public:
int a;
int b;
int c;
};
then you could use list initialization:
myvector.push_back({a, b, c});
But it could be better to make a constructor
MyClass::MyClass(int a, int b, int c):
a(a), b(b), c(c)
{}
and then use vector::emplace_back
myvector.emplace_back(a, b, c);
To make it work you need at least a C++11 compiler and you need to make a constructor:
class MyClass {
int a;
int b;
int c;
public:
MyClass(int a_, int b_, int c_) : a(a_), b(b_), c(c_) {}
};
You could also make a, b and c public, but I'm guessing you don't want to do that, as it changes the interface of the class.
In response to your question "why is emplace_back better or more efficient than push_back":
By design, emplace_back() should avoid creating a temporary object and should construct "in place" at the end of the vector. With push_back({a, b, c}) you create a temporary MyClass object, which is then copied to the end of the vector. Of course, compiler optimizations may actually lead to same code being generated in both cases, but, by default, emplace_back() should be more efficient. This is further discussed here: push_back vs emplace_back .

C++ constant structure initialization inside a class

How should I write a constructor for a class to initialize a member that is a const structure / has const fields?
In the following example, I define a constructor within structure B and it works fine to initialize it's const fields.
But when I try to use the same technique to initialize const fields of structure C within class A it doesn't work. Can someone please help me and rewrite my class A in a way, that it starts working?
#include <iostream>
class A
{
public:
struct C
{
C (const int _x) : x (_x) {}
const int x;
};
C c (3);
};
int main (int argc, char *argv[])
{
struct B
{
B (const int _x) : x (_x) {}
const int x;
};
B b (2);
std::cout << b.x << std::endl;
A a;
std::cout << a.c.x << std::endl;
return 0;
}
P.S.
I did some search and I think, I understand, that unless I have C++11 support or want to use boost library, I have to define a helper function to initialize a const struct within initialization list
(C++ Constant structure member initialization)
but it seems to be crazy that I have to define alike struct, but with non const fields to initialize a struct with const fields, doesn't it?
Another thing that I found tells that I should initialize const members in a constructor of the class A, rather than in a constructor of the struct C (C++ compile time error: expected identifier before numeric constant) but it also seems crazy to me, because why should I rewrite a class constructor every time I want to add a new struct, isn't it more convenient to have a separate constructor for each struct C within the class A?
I would be grateful to any comments that could possibly clarify my confusion.
I'd do the job like this:
#include <iostream>
class A {
public:
struct C {
C(const int _x) : x(_x) {}
const int x;
};
C c; // (3);
A() : c(3) {}
};
int main(int argc, char *argv []) {
A a;
std::cout << a.c.x << std::endl;
return 0;
}
Note that it's not a matter of using a ctor in A or in C, but of the ctor for A telling how the ctor for C should be invoked. If the value that will be passed will always be 3 that's not necessary, but I'm assuming you want to be a able to pass a value of your choice when you create the C object, and it will remain constant after that.
If the value will always be the same (3 in this case) you can simplify things a lot by also making the constant static:
struct A {
struct C {
static const int x = 3;
};
C c;
};
int main() {
A a;
std::cout << a.c.x << "\n";
}
So, if the value is identical for all instances of that class, make it static const, initialize it in place, and life is good. If the value is not known until you create an instance of the object, and remains constant thereafter for the life of that object, you need to pass it in through the constructors.
For a slightly different case, there's a third possibility: if C is an independent class (not nested inside of A) you might have a situation where other instances of C use various values, but all instances of C inside an A always use the same value. In this case, you'd do something like:
struct C {
const int x;
C(int x) : x(x) {}
};
struct A {
C c;
A() : c(3) {}
};
Of course, you can do the same thing when C is nested inside of A, but when/if you do, it generally means you're setting the same value for all instances of C, so you might as well use the static const approach instead. The obvious exception would be if A had multiple constructors, so (for example) A's default constructor passed one value for C::x and its copy constructor passed a different value.

Temporaries created during assignment operation

if every assignment creates a temporary to copy the object into lvalue, how can you check to see in VC++ 8.0?
class E
{
int i, j;
public:
E():i(0), j(0){}
E(int I, int J):i(I), j(J){}
};
int main()
{
E a;
E b(1, 2);
a = b //would there be created two copies of b?
}
Edit:
Case 2:
class A
{
int i, j;
public:
A():i(0), j(0){}
};
class E
{
int i, j;
A a;
public:
E():i(0), j(0){}
E(int I, int J):i(I), j(J){}
E(const E &temp)
{
a = temp; //temporary copy made?
}
};
int main()
{
E a;
E b(1, 2);
a = b //would there be created two copies of b?
}
From your comment, you made it clear that you didn't quite understand this C++-FAQ item.
First of all, there are no temporaries in the code you presented. The compiler declared A::operator= is called, and you simply end up with 1 in a.i and 2 in a.j.
Now, regarding the link you provided, it has to do with constructors only. In the following code :
class A
{
public:
A()
{
s = "foo";
}
private:
std::string s;
};
The data member s is constructed using std::string parameterless constructor, then is assigned the value "foo" in A constructor body. It's preferable (and as a matter of fact necessary in some cases) to initialize data members in an initialization list, just like you did with i and j :
A() : s("foo")
{
}
Here, the s data member is initialized in one step : by calling the appropriate constructor.
There are a few standard methods that are created automatically for you if you don't provide them. If you write
struct Foo
{
int i, j;
Foo(int i, int j) : i(i), j(j) {}
};
the compiler completes that to
struct Foo
{
int i, j;
Foo(int i, int j) : i(i), j(j)
{
}
Foo(const Foo& other) : i(other.i), j(other.j)
{
}
Foo& operator=(const Foo& other)
{
i = other.i; j = other.j;
return *this;
}
};
In other words you will normally get a copy constructor and an assignment operator that work on an member-by-member basis. In the specific the assignment operator doesn't build any temporary object.
It's very important to understand how those implicitly defined method works because most of the time they're exact the right thing you need, but sometimes they're completely wrong (for example if your members are pointers often a member-by-member copy or assignment is not the correct way to handle the operation).
This would create a temporary:
E makeE( int i, int j )
{
return E(i, j);
}
int main()
{
E a;
a = makeE( 1, 2 );
E b = makeE( 3, 4 );
}
makeE returns a temporary. a is assigned to the temporary and the assignment operator is always called here. b is not "assigned to", as it is being initialised here, and requires an accessible copy-constructor for that to work although it is not guaranteed that the copy-constructor will actually be called as the compiler might optimise it away.