Sou*_*a B 4 c++ std qualified-name argument-dependent-lookup unqualified-name
当我用 C++ 编程时,using namespace std;我通常倾向于使用std::前缀组件,例如等std::cout,而不是编写std::cin。但是后来我遇到了 ADL 以及为什么应该使用using std::swap;。
标准库(在 std 内)的许多组件以不合格的方式调用交换,以允许调用非基本类型的自定义重载,而不是此通用版本:在与其所属类型相同的命名空间中声明的交换的自定义重载提供通过对此通用版本进行参数相关的查找来选择。
但在所有有关 ADL 的资料中,他们只提到std::swap. 还有其他类似的功能在使用时需要注意吗?或者对于所有其他功能,我应该使用完全限定名称吗?或者我应该为中的每个函数使用非限定名称std::?
编辑:(在表达我最初的问题时,我不清楚。这是我在写问题时的确切意图。)
C++ 标准库中是否还有其他函数是基于 ADL 的自定义的热门候选函数,类似于std::swap,因此当我使用它们时,我必须谨慎使用using std::foo; foo();表单而不是std::foo();直接调用?
假设您编写了一个与用户提供的类型一起使用的库。那么您可能想为 foo a bar 提供默认实现。但同时您希望用户能够提供他们的自定义实现,因为他们可能更知道如何设置他们的自定义栏。
这正是标准库中发生的情况std::swap。依赖 ADL 的代码位于库内部,它适用于自定义类型,在实例化之前它不知道类型。它可以提供默认值std::swap,但同时允许用户提供自己的实现。
在您的用户代码中,当您知道类型时,通常您想知道调用了什么函数。通常,您确实知道是否要致电my::swap或,std::swap并且不需要 ADL 来选择。
话虽如此,如果您必须问这个问题,那么答案是:不要使用 ADL。(我知道“如果你必须问……”有点愚蠢,但有时这太适用了)。即使在库代码中,您也不总是希望启用 ADL,或允许将其作为自定义。即使您确实编写了通用代码,也可能在某些情况下您需要自己的方式来 foo 酒吧而不允许用户自定义它。这确实取决于。
简短回答:如果您想打电话,std::swap请致电std::swap。如果你想打电话my::swap就打电话my::swap。如果您想利用 ADL,您就会知道该怎么做。
PS:还有更多您知道但可能不知道的 ADL 示例。std::例如,当您调用运算符重载时,您几乎从不使用前缀。例如std::string operator+(const std::string&,const std::string&)。你可以写
std::string a,b;
auto c = std::operator+(a,b);
Run Code Online (Sandbox Code Playgroud)
但你没有。你习惯了写
auto c = a + b;
Run Code Online (Sandbox Code Playgroud)
这仅在 ADL 的情况下有效。
PPS:即使std::swap它“不应该以”为前缀也是不对的std::。如上所述,有时您确实想使用 ADL,有时则不想。该决定不是针对每个功能,而是针对每个用例。如果您编写交换两个对象的代码,并且出于某种原因您只想调用std::swap而不是其他,那么您可以调用std::swap. 如果您想利用 ADL,那么您就利用 ADL。