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

How to remove the current function from the overload set?

本文关键字:函数 删除 集中 重载      更新时间:2023-10-16

我的命名空间中有一个函数,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::foo更好的匹配foons::foo 就是递归的。

我不想给ns::foo一个不同的名字,那么有没有办法把它从自身内部的过载中移除呢?

如果要调度到的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调用foo不会考虑ns::foo,因为它不在依赖于参数的命名空间中。当然,除非x的类型恰好是ns,但根据定义,您有一个递归。

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

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

没有递归,因为 helper::_foo 函数无法调用template foo,因为它仍未定义。

如果使用额外的参数定义 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
}