swap method for a class inherited from enable_shared_from_this<...>

49 Views Asked by At

I have implemented a swap method for my class that inherits from enable_shared_from_this<...>

class X : public enable_shared_from_this<X> {
    int x;
    friend void swap(X& x1, X& x2) {
        using std::swap;
        swap(x1.x, x2.x);
    }
    X& operator=(X other) {
       swap(*this, other);
    }
    ...
}

I tried to swap the enable_shared_from_this<...> part in the swap method by adding either:

std::enable_shared_from_this<X>::swap(first, second);

Doesn't compile because of:

No member named 'swap' in 'std::enable_shared_from_this'

swap(static_cast<std::enable_shared_from_this<X>>(first), static_cast<std::enable_shared_from_this<X>>(second));

Doesn't compile because of:

Calling a protected constructor of class 'std::enable_shared_from_this' protected constructor can only be used to construct a base class subobject

Finally I resorted to adding the following line in the assignment operator:

std::enable_shared_from_this<X>::operator=(other);

But this feels wrong to me because the swap method is incomplete and in general mixing two idioms (I guess).

So what is the correct way to handle this...?

Note: I'm using C++20.

1

There are 1 best solutions below

5
Nicol Bolas On

enable_shared_from_this technically has a copy constructor and assignment operator. But they don't meaningfully work. Neither of them copies the weak_this internal member. So even after assignment, the weak_this will be the same.

Swapping is not functionality that enable_shared_from_this supports.

Note that swapping them wouldn't actually make sense. The shared_ptrs managing the memory for each object point to the specific objects they manage. Swapping objects only swaps their contents; the address of the two objects remains the same. So the managed storage should still refer to the original objects because their addresses didn't change.

As such, it makes sense that you cannot "copy" or "swap" enable_shared_from_this. So just leave the base class subobjects alone.