Koenig 查找参数

Koenig lookup for arguments

Koenig 查找参数的想法是坏事吗?

有了 ADL,我们有:

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

baz(foo::bar());

为什么我们没有这样的东西:

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

foo::baz(bar());

Is idea of Koenig lookup for arguments a bad thing?

绝对不是。它允许将非成员 API 放置在它所属的位置:与您的类型相同的命名空间;它不会强制用户在调用函数时了解命名空间。
考虑一下 sort(begin(vec), end(vec));std::sort(std::begin(vec), std::end(vec));

相比有多方便

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

And why we don't have something like:

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

foo::baz(bar());

因为它比相反的更容易含糊不清。如果 foo::baz 在不同的命名空间中为 bar 重载怎么办?如果没有完全限定它,你将无法与另一个 bar 一起调用它。

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

Is idea of Koenig lookup for arguments a bad thing?

完全没有。考虑运算符重载的场景,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?
}