Pregunta

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?

¿Fue útil?

Solución

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.

Otros consejos

If you define your ADL functions with an extra argument, it gives it a different type signature, so you won't have a conflict. I defined the template in global scope, but it will work in the ns scope as well.

namespace ns
{
   class A {};
   class B {};
   void foo(A, int) { std::cout << "adl: fooA" << std::endl; }
   void foo(B, int) { std::cout << "adl: fooB" << std::endl; }
}

template <typename T>
void foo(T t) {
   foo(t, 0);
}

int main()
{
   ns::A a;
   ns::B b;
   foo(a);    //calls ns::foo
   foo(b);    //calls ns::foo
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top