I have an application with a few layers of components. Say that the bottom component is A and there are components B, C, D on top of it.
Say I have a method in every component, named the same, for example 'getMeSomething', which is called from D. D calls C, C calls B, B calls A. Every component has a chance to do something before calling other component, and a chance to do something with the thing that it gets in return (based on some argument). It can even decide to return new Something object instead of calling lower components.
So, for example, when 'D' component calls method in 'C' component by:
// code from D class
Something s = c.getMeSomething(1)
In the 'C' component it is handled like this:
Something C::getMeSomething(int arg)
{
if (arg == 1)
{
Log ("Hey, I've got 1");
Something sth = b.getMeSomething();
sth.remove(arg); // or whatever method on sth
}
else if (arg == 2)
{
return b.getMeSomething();
}
else
{
return Something(123); // whatever here
}
}
Similar things happen in B and in A.
What I am concerned about is returning the Something by value. The Something can be big and I would like to make sure it can be efficiently passed, at least in these cases when nothing must be done in particular layer about this Something object (see the case when 'arg == 2' above).
For example, in case when A returns Something and B returns the same object without touching it, and C also just returns the same object to D, I would like to avoid copying. I would like the Something be moved, not copied.
How can I be sure that move is used in this case? Can I? What should I do to provide moveability?
I guess I should provide the move constructor to Something class (or make sure it can be auto-generated by compiler). Am I right?
But what about the cases when one layer affects the Something object. Will that affect the whole situation, I mean the cases when the Something is just passed on to next layer?
And what about copy-elission? Will the compiler use this techique instead of moving? What are the rules here?
A more verbous example (with 3 components, for simplicity).
#include <iostream>
#include <cassert>
struct Sth
{
int x;
};
struct A
{
Sth get(int i) { return Sth{333}; }
};
struct B
{
A a;
Sth get(int i)
{
if (i == 1)
return a.get(i);
else
{
Sth s = a.get(i);
s.x = 444;
return s;
}
}
};
struct C
{
B b;
Sth get(int i) { return b.get(i); }
};
int main()
{
C c;
Sth s1 = c.get(1);
assert (s1.x == 333);
Sth s2 = c.get(2);
assert (s2.x == 444);
}