I have come across the situation where I really do need to execute non-trivial code in a copy-constructor/assignment-operator. The correctness of the algorithm depends on it.
While I could disable return value optimisation with a compiler switch, it seems a waste because it's only the one type I need it disabled for, so why should the performance of the whole application suffer? (Not to mention that my company would not allow me to add the switch, anyway).
struct A {
explicit A(double val) : m_val(val) {}
A(const A& other) : m_val(other.m_val) {
// Do something really important here
}
A& operator=(const A& other) {
if (&other != this) {
m_val = other.m_val;
// Do something really important here
}
return *this;
}
double m_val;
};
A operator+(const A& a1, const A& a2) {
A retVal(a1.m_val + a2.m_val);
// Do something else important
return retVal;
}
// Implement other operators like *,+,-,/ etc.
This class would be used as such:
A a1(3), a2(4), a3(5);
A a4 = (a1 + a2) * a3 / a1;
Return value optimisation means that a4 will not be created with the copy constructor, and the "really important thing to do" does not happen!
I know I could hack in a solution where operator+ returns a different type (B, say) and have an A constructor that takes a B as input. But then the number of operators needed to be implemented explodes:
B operator+(const A& a1, const A& a2);
B operator+(const B& a1, const A& a2);
B operator+(const A& a1, const B& a2);
B operator+(const B& a1, const B& a2);
There must be a better solution. How can I hack it so that RVO does not happen for my type? I can only change the A class code and the operators. I can't change the calling site code; i.e. I can't do this:
A a1(3), a2(4), a3(5);
A a4;
a4 = (a1 + a2) * a3 / a1;
One thing I've considered trying is to try and experiment with C++11 move constructors, but I'm not sure this would work, and I don't like it not being valid in C++03.
Any ideas?
EDIT: Please just accept that this is the only way I can do what I need to do. I cannot just 'change the design'. The calling code is fixed, and I must implement my strategy inside the mathematical operators and copy constructor & assignment operator. The idea is that the intermediate values calculated inside the "a4 = (a1+a2)*a3/a1" equation cannot be referenced anywhere else in the program - but a4 can. I know this is vague but you'll just have to live with it.