如何从过载集中删除当前函数?

时间:2012-06-15 22:10:07

标签: c++ argument-dependent-lookup

我的命名空间中有一个函数ns::foo,其作用是使用依赖于参数的查找调度foo的调用:

namespace ns
{

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

}

我希望客户能够在不必手动实例化的情况下调用foo,即:

bar x;
ns::foo(x);

ns::foo<bar>(x);

问题当然是如果ns::foofoo没有更好的匹配,则ns::foo是递归的。

我不想给ns::foo一个不同的名字,所以有没有办法将它从内部的重载集中删除?

2 个答案:

答案 0 :(得分:4)

如果您要分派的foo不在ns命名空间中,那么这应该有效:

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);
    }
}

诀窍是来自foo的{​​{1}}调用不会考虑_foo,因为它不在依赖于参数的命名空间中。除非ns::foo的类型当然恰好位于x,但是根据定义你递归。

更新:您必须在 ns的定义之后将此代码放在之后:

namespace ns

没有递归,因为namespace ns { //your useful stuff here } namespace helper { /* template _foo */ } namespace ns { /* template foo */ } 函数无法调用helper::_foo,因为它仍未定义。

答案 1 :(得分:1)

如果使用额外参数定义ADL函数,则会为其提供不同的类型签名,因此不会发生冲突。我在全局范围内定义了模板,但它也适用于ns范围。

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
}