Koenig查找参数

时间:2016-11-10 15:14:05

标签: c++ argument-dependent-lookup

Koenig是否认为参数是一件坏事?

使用ADL,我们有:

namespace foo
{
    struct bar {};
    void baz(bar);
}

baz(foo::bar());

为什么我们没有类似的东西:

namespace foo
{
  struct bar {};
  void baz(bar);
} // namespace foo

foo::baz(bar());

3 个答案:

答案 0 :(得分:4)

  

Koenig是否认为参数是一件坏事?

绝对不是。它允许在其所属的位置放置非成员API:与您的类型相同的命名空间;它可以在不调用函数的情况下强制用户知道命名空间 考虑编写sort(begin(vec), end(vec));而不是std::sort(std::begin(vec), std::end(vec));

是多么方便

当你重载运算符时,它也是必须的。

  

为什么我们没有类似的东西:

namespace foo
{
  struct bar {};
  void baz(bar);
} // namespace foo

foo::baz(bar());

因为它比相反的更容易模棱两可。如果foo::baz在不同的命名空间中为bar重载会怎样?如果没有完全符合条件,你就无法与其他bar一起调用它。

答案 1 :(得分:2)

关注非重复部分,为什么不foo::baz(bar());?原因很简单,在C ++中,解析树始终从头到尾处理。函数名称的名称查找取决于函数参数,而不是相反,就像重载决策取决于参数类型而不是返回类型一样。

答案 2 :(得分:2)

  

Koenig是否认为参数是一件坏事?

完全没有。考虑运算符重载的场景,ADL可以使用在不同命名空间中定义的运算符。

namespace foo
{
    struct bar {};
    bar operator+ (const bar& lhs, const bar&rhs);
}

使用ADL,我们可以写

foo::bar b1, b2;
auto b3 = b1 + b2; // natural as operator

没有ADL,我们必须写

auto b3 = foo::operator+(b1, b2); // unnatural

作为旁注,STL的所有重载运算符都在名称空间std中定义。如果没有ADL,我们甚至可以直截了当地称呼它们。

此外,如果没有ADL,模板将面临挑战。

template <typename T>
T add(const T& lhs, const T& rhs) {
    return What_Namespace::operator+(lhs, rhs); // how to deduce the name of namespace?
}