Koenig是否认为参数是一件坏事?
使用ADL,我们有:
namespace foo
{
struct bar {};
void baz(bar);
}
baz(foo::bar());
为什么我们没有类似的东西:
namespace foo
{
struct bar {};
void baz(bar);
} // namespace foo
foo::baz(bar());
答案 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?
}