There are times when I wish to augment the default copy/move operations (e.g. logging; profiling; tracking the object as it's moved/copied). Currently, it's only possible to replace them completely, which means having to maintain the code that copies/moves the data members (and base classes).

widget(widget&& o)
: a(std::move(o.a))
, b(std::move(o.b))
, c(std::move(o.c))
{
    foo(a, b, c);
}

widget& operator=(widget&& o)
{
    a = std::move(o.a);
    b = std::move(o.b);
    c = std::move(o.c);
    foo(a, b, c);
    return *this;
}

Why not allow delegating to a compiler generated implementation? For example (tentative syntax):

widget(widget&& o)
: default widget(std::move(o))
{
    foo(a, b, c);
}

widget& operator=(widget&& o)
{
    default operator=(std::move(o));
    foo(a, b, c);
    return *this;
}

Of course, there are existing workarounds, like moving the data members into a separate struct or base class. But such boilerplate seems unnecessary when the compiler could (and would otherwise) easily generate it for you.

Just floating the idea to see what people think.

p.s. I did see a recent thread proposing a similar idea, to automatically copy/move specific data members only. But my suggestion is about invoking the default behaviour wholesale rather than picking pieces of it. I believe the use cases are quite different.