1

我的命名空间中有一个函数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是如果没有foo比更好的匹配,那就是递归的ns::foo

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

4

2 回答 2

4

如果foo要分派的 to 不在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);
    }
}

诀窍是对foofrom的调用_foo不会考虑ns::foo,因为它不在依赖于参数的命名空间中。除非x碰巧的类型ns当然是 in,但是你一个定义的递归。

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

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

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

于 2012-06-15T22:30:05.883 回答
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
}
于 2012-06-15T22:25:43.827 回答