Search code examples
c++argument-dependent-lookup

How to remove the current function from the overload set?


I have a function in my namespace, ns::foo, whose job is to dispatch an invocation of foo using argument-dependent lookup:

namespace ns
{

template<typename T>
void foo(T x)
{
  // call foo through ADL
  foo(x);
}

}

I want clients to be able to call foo without having to manually instantiate it, i.e.:

bar x;
ns::foo(x);

Not

ns::foo<bar>(x);

The problem of course is that ns::foo is recursive if there is no better match for foo than ns::foo.

I don't wish to give ns::foo a different name, so is there any way to remove it from the overload set inside itself?


Solution

  • If the foo to where you want to dispatch is not in the ns namespace, then this should work:

    namespace helper
    {
        template<typename T>
        void _foo(T x)
        {
            // call foo through ADL
            foo(x);
        }
    }
    
    namespace ns
    {
        template<typename T>
        void foo(T x)
        {
          ::helper::_foo(x);
        }
    }
    

    The trick is that the call to foo from _foo will not consider ns::foo, because it is not in an argument-dependent namespace. Unless the type of x happens to be in ns of course, but then you have a recursion by definition.

    UPDATE: You have to put this code just after the definition of namespace ns:

    namespace ns
    {
         //your useful stuff here
    }
    namespace helper { /* template _foo */ }
    namespace ns { /* template foo */ }
    

    There is no recursion because the helper::_foo function cannot call the template foo because it is still not defined.