我的命名空间中有一个函数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
一个不同的名字,所以有没有办法将它从内部的重载集中删除?
答案 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
}