4

在 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
}

我尝试了显式实例化,但它没有改变任何东西(即使它会改变,它也比仅仅使用using更糟糕)。

那么,为什么我不能在不指定其命名空间的情况下调用模板化函数(并且假设既不使用也不使用命名空间指令)?

4

1 回答 1

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_*需要一个强制参数来表示所需结果类型的函数。)

于 2012-11-12T18:21:54.627 回答