A common thing I find myself doing is making \"almost default\" copy constructors and assignment operators. That is, I find myself in situations where the compiler supplied copy
If you can isolate the specific handling in a proper RAII wrapper as Igor Tandetnik suggested: go for that.
If you still need specific processing in the copy constructor and/or assignment operator (such as register the object creation/assignment in a container or log), you can group the data members that can be default copy constructed/assigned into a separate class that you use as a base class or data member, which you handle as composite, thus:
struct x_base {
int a,b,c,d;
std::string name;
};
struct x : x_base {
x(const x& other)
: x_base(other)
{
descr = "copied ";
descr += name;
descr += " at ";
descr += CurrentTimeAsString();
std::cout << descr << "\n";
}
void operator = (const x& other)
{
x_base::operator =(other);
descr = "assigned ";
descr += name;
descr += " at ";
descr += CurrentTimeAsString();
std::cout << descr << "\n";
}
std::string descr;
};
When you later add data members that don't need specific handling, you can simply add them to x_base.