在C ++中,我们可以在使用函数时省略命名空间限定,该函数将第一个参数作为与函数在同一名称空间中声明的类型对象。但是,我注意到这不适用于模板化函数(如 std :: get )。我写了一个简单的例子来确认这与模板真的有关:
namespace ns {
struct S {};
void sFoo(const S&) {}
template<typename T> void sBar(const S&) {}
}
void foo()
{
ns::S s;
sFoo(s); // ok
sBar<int>(s); // error: ‘sBar’ was not declared in this scope
ns::sBar<int>(s); // ok
}
我尝试了显式实例化,但它没有改变任何东西(即使它会,它会比使用使用更糟糕的选择)。
那么为什么我不能在没有指定命名空间的情况下调用模板化函数(假设使用或使用命名空间指令)?
答案 0 :(得分:2)
sBar
不是函数,而是函数模板。参数依赖查找仅适用于函数名称。 sBar<int>
是一个函数,但如果您不知道它的正确名称,则无法实例化该模板!
无关紧要,如果可以推导出模板参数,那ADL确实有效:
namespace ns
{
template <typename T> void sZip(T &) { }
}
void foo()
{
ns::S s;
sZip(s); // OK, deduces T = ns::S
}
C ++的一般“最佳实践”是,只有在可以推导出参数的情况下才能生成函数模板,并且永远不要明确指定参数。 (此规则的例外情况是std::forward
和各种make_*
函数,这些函数需要一个强制参数用于所需的结果类型。)