为什么要发明参数依赖查找?
为什么要发明参数依赖查找(ADL)?是不是我们就可以这样写 cout << stuff
而不是 std::operator<<(cout, stuff)
?如果是这样的话,为什么 ADL 不限于运算符而不是所有函数?
如果 C++ 有其他方法来执行内置类型和用户定义类型的通用输出(例如通过可变参数模板的类型安全 printf
),ADL 的引入是否可以被阻止?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
ADL 的发明是为了允许接口原则:
接口原则
对于类 X,所有函数,包括自由函数,都
在逻辑上是 X 的一部分,因为它们构成了 X 接口的一部分。
查看 Herb Sutter 的优秀文章 关于该主题的本周大师。
ADL was invented to allow the Interface Principle:
The Interface Principle
For a class X, all functions, including free functions, that both
are logically part of X, because they form part of the interface of X.
Check out Herb Sutter's excellent Guru of the Week on the topic.
为什么要人为限制呢? ADL 的实现可能比较棘手(与 C++ 的重载规则结合使用时)1,但它是一种非常有用的技术。一方面,它也适用于函数这一事实使得使用其他命名空间变得更加容易,而无需导入整个命名空间。
举个例子,SeqAn 库:
请注意,我使用了函数
seqan::length< /code> 没有限定其全名。无论如何,ADL 都会找到它。 SeqAn 库过度使用此类命名空间范围的函数,并且为每个用法添加命名空间名称前缀是不切实际的。同样,导入命名空间通常也是不可取的。
当然,许多其他库也是如此,例如大多数 Boost 库。
1 我相信委员会并没有立即意识到这一点。
Why limit it artificially? ADL may be tricky to implement (when combined with C++’ overloading rules)1 but it’s an extremely useful technique. For one thing, the fact that it also works on functions makes it much easier to use other namespaces without importing the whole namespace.
Case in point, the SeqAn library:
Notice that I’ve used the function
seqan::length
without qualifying its full name. ADL finds it anyway. The SeqAn library uses such namespace-scope functions excessively and prefixing every usage with the namespace name would be impractical. Likewise, importing the namespace often isn’t advisable.The same is of course true for many other libraries, such as most of Boost’s.
1 And I believe that this wasn’t immediately realized by the committee.
让我们看一个简单的通用算法:
它如何处理自定义类型及其自己的
swap
版本?感谢ADL。正如丹尼尔提到的,这就是萨特所说的接口原则。
Let's look at a simple generic algorithm:
How does it work with custom types and their own version of
swap
? Thanks to ADL.This is what Sutter calls the Interface Principle, as Daniel mentioned.
它的发明是为了允许函数多态性。这个想法是,该功能是一个动词(如“print”),它只有一个含义。根据动词的适用范围(如 int 和 float 和 std::string),仍然可以有不同的实现。
因此,我们需要一个词来描述这个概念,但需要根据它的应用场合有几个实现。
它适用于参数。因此,我们需要一种方法来在多个不同类型的参数上使用相同的单词,并在需要时使用参数类型相对实现。
尝试使用 printInt()、printString()、printFloat() 函数编写复杂的串联,您会看到明显的冗长。
另一个原因是它允许检查给定参数类型的实现是否可用。如果没有可用的实现(甚至没有通用的 - 使用模板),那么编译器会尽快阻止您,并让您知道它没有给定参数的动词的实现。
It was invented to allow function polymorphism. The idea is that the function being a verb (like "print"), it have only one meaning. Still there can be different implementation depending on what the verb apply to (like int and float and std::string).
So we want one word for the concept but several implementation depending on what it's applied to.
What it's applied to is the argument(s). So we needed a way to use the same word on several différent type of arguments with - where needed- argument-type-relative implementation.
Try to write a complex concatenation with printInt(), printString(), printFloat() functions, you'll see the obvious verbosity.
The other reason is that it allows to check wich implementation are available for the givent argument type. If there is no implementation available (not even generic - using templates) then the compiler stop you as soon as he can and makes you know that it don't have an implementation of your verb for the given argument.
是的,它主要是为操作员发明的。但它还使您能够将非成员函数包含到类的接口中。这是一个非常强大的东西,我非常喜欢。这不再局限于运营商。例如,您可能想为您的
vector
类定义一个cross_product
函数 - 您知道我的意思:)Yes, it was mostly invented for operators. But it also gives you the ability to incude nonmember functions into the interface of your class. And this is a very powerful thing which I like a lot. And this isn't limited to operators any more. For example, you could want to define a
cross_product
function for yourvector
class - you know what I mean :)