Search code examples
c++c++17swapoverload-resolutionargument-dependent-lookup

Implementing member swap() in terms of non-member swap()


I'm implementing a class with a similar interface to std::array, which has both the member swap() and the non-member swap().

Since I want my class to mimic the standard containers, I would like to implement both kinds of swap() (the non-member swap() is implemented via ADL, since specializing std::swap() isn't permitted):

class A {
    public:
        friend void swap(A& a, A& b) { /* swap the stuff */ }
        void swap(A& other) { swap(*this, other); }
};

However, it seems like I can't call the non-member swap() from inside the class, because it prefers the member swap() even though it only has a single parameter. Changing it to ::swap(*this, other) doesn't work as well, because the in-class friend function is only findable via ADL. How might I call the non-member swap() from inside the class?


Solution

  • The problem is that the name of the member function swap hides the namespace-scope swap in the body of A::swap. Unqualified name lookup for swap in A::swap will never find namespace-scope swap and, thus, namespace-scope swap will not be part of the overload set. One way to get around this would be to simply add a declaration for namespace-scope swap in the body of A::swap:

    class A
    {
    public:
        friend void swap(A& a, A& b) { /* swap the stuff */ }
    
        void swap(A& other)
        {
            void swap(A& a, A& b);
            swap(*this, other);
        }
    };
    

    That being said, I'm not sure what this really does for you. The obvious solution is to just implement namespace-scope swap in terms of A::swap rather than the other way around. Personally, I would just not have a swap member function to begin with. The typical way of swapping aand b is to just swap(a, b)