Search code examples
c++namespacesoverload-resolutionambiguous-call

How do I make std::sort not have name collision between std::swap and my namespace's templated swap?


I want to use std::sort, but the compile is failing with error C2668: std::swap: ambiguous call to overloaded function because there is a templated swap() function defined in my namespace that would be hard to get rid of. I don't care which swap it uses, but how do I make either one of them go away when compiling sort()?

I understand that it's ambiguous because my::swap is in the same namespace as my::Obj, and I don't care which version of swap gets used. I just have to overcome the namespace collision. This is part of a very large code base that I don't own so I'm hoping for a solution that is local to my code and presumably allows my::Obj and my::swapto both stay in namespace my.

namespace my
{
    template<class T> void swap(T a, T b)
    {
    }

    struct Obj
    {
    };

    void doSortStuff()
    {
        std::vector<Obj> arr;
        std::sort(arr.begin(), arr.end());
    }
};

Solution

  • A workaround is to create a better overload:

    // No modifiable code
    namespace my
    {
        template<class T> void swap(T a, T b) { /*.. */ }
        struct Obj { /*..*/ };
    }
    
    // Your code:
    namespace my
    {
        void swap(Obj& lhs, Obj& rhs)
        {
            // my::swap<Obj&>(lhs, rhs);
            std::swap(lhs, rhs);
        }
    }
    
    // In namespace you want.
    void doSortStuff()
    {
        std::vector<my::Obj> arr;
        std::sort(arr.begin(), arr.end());
    }
    

    Then, between the 3 valid overloads, all are exact match, but the non-template is preferred.