问题标签 [argument-dependent-lookup]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - Should custom containers have free begin/end functions?
When creating a custom container class that plays by the usual rules (i.e. works with STL algorithms, works with well-behaved generic code, etc.), in C++03 it was sufficient to implement iterator support and member begin/end functions.
C++11 introduces two new concepts - range-based for loop and std::begin/end. Range-based for loop understands member begin/end functions, so any C++03 containers support range-based for out of the box. For algorithms the recommended way (according to 'Writing modern C++ code' by Herb Sutter) is to use std::begin instead of member function.
However, at this point I have to ask - is the recommended way to call a fully qualified begin() function (i.e. std::begin(c)) or to rely on ADL and call begin(c)?
ADL seems useless in this particular case - since std::begin(c) delegates to c.begin() if possible, usual ADL benefits do not seem to apply. And if everybody starts to rely on ADL, all custom containers have to implement extra begin()/end() free functions in their requisite namespaces. However, several sources seem to imply that unqualified calls to begin/end are the recommended way (i.e. https://svn.boost.org/trac/boost/ticket/6357).
So what is the C++11 way? Should container library authors write extra begin/end functions for their classes to support unqualified begin/end calls in absence of using namespace std; or using std::begin;?
c++ - VS2012 上的 decltype 内没有 ADL
我刚刚意识到尝试通过 decltype 获取函数的返回类型不涉及 VS2012 上的 ADL(参数相关查找)(使用 cl.exe V17.00.60610.1 测试)。
下面的例子
给
在 VS2012 上
但是(预期的):
在 gcc 4.7.3 上。
因此,ADL 在调用函数(输出中的第 1 行)时有效,但在 VS2012 上的 decltype 内使用时无效。
还是我错过了一些不同的观点?
c++ - 哪个函数用于初始化静态类成员?
我有一个关于选择哪个函数来初始化静态类成员的问题。
该变量Base::count
是使用Base::countInit()
而不是countInit()
在 Base.cpp 中定义的进行初始化的。但是local_count
是由本地初始化的countInit
。所以,我想知道,在这种情况下是否有像Koenig 查找这样的规则?
c++ - 同名成员函数的 ADL
情况是某些成员函数bar::Bar::frobnicate
想利用 ADL 从某个未知名称空间中找到一个函数,该函数在一个具有相同名称的函数中。但是,它只能找到自己的名称。
测试用例
(请注意,实际上,Bar
是一个Foo
不可知的模板;这只是可重现的最小测试用例)
结果是:
标准
我知道这是正确的编译器行为:
3.4.1 非限定名称查找[basic.lookup.unqual]
(...) 一旦找到名称 (...) 的声明,名称查找就会结束
并且只有在不合格的查找失败后,依赖于参数的查找才起作用:
3.4.2 依赖于参数的名称查找[basic.lookup.argdep]
当函数调用 (5.2.2) 中的后缀表达式是非限定 ID 时,可能会搜索在通常的非限定查找 (3.4.1) 期间未考虑的其他命名空间
解决方法
我目前的解决方法是引入一个不定义冲突名称本身的特殊特征类:
或者这个更轻的版本:
问题
有没有比引入此类特征类更好的选择?
在这里明确限定调用foo::frobnicate(foo)
不是一个选项,因为(如前所述)Bar
该类实际上是一个模板,Foo
并且不应仅适用于foo
命名空间中的类型。
c++ - Bjarne 对这个 ADL 示例是否有错误,或者我有编译器错误?
我正在阅读The C++ Programming Language, 4th Edition (by Bjarne Stroustrup ) 关于argument-dependent-lookup。这是引用(26.3.6,过度激进的 ADL):
依赖于参数的查找(通常称为 ADL)对于避免冗长(14.2.4)非常有用。例如:
如果没有依赖于参数的查找,
endl
将找不到操纵器。实际上,编译器注意到 的第一个参数<<
是在ostream
中定义的std
。因此,它查找endl
instd
并找到它 (in<iostream>
)。
这是编译器产生的结果(C++11 模式):
这是编译器或书中的错误。标准是怎么说的?
更新:
我需要澄清一下。我知道正确的答案是使用std::endl
. 问题是关于书中的文字。正如Lachlan Easton已经说过的,这不仅仅是一个错字。整个段落(可能)是错误的。如果这本书是另一位(鲜为人知的)作者写的,我可以接受这种错误,但我一直(现在仍然)怀疑,因为它是由 Bjarne 写的。
c++ - 是否可以获取 ADL 函数的地址?
是否可以获取通过 ADL 找到的函数的地址?
例如:
c++ - 通过使用指令调用开始和结束?
调用的既定习惯用法swap
是:
这样,swap
可以为std
命名空间之外的用户定义类型重载。
我们应该以同样的方式调用begin
and吗?end
或者我们应该写:
c++ - 为什么编译器找不到这个 operator<< 重载?
我正在尝试为operator<<
将存储在boost::variant
. 这是一个说明问题的小例子:
Clang 的第一个错误是
我意识到这#include <boost/variant.hpp>
是在一个奇怪的地方。我很确定这个问题与模板中的两阶段名称查找有关,所以我移动了#include
它以尝试从关于 lookup 的 clang 文档中实现修复 #1 。该文档中的修复 #2 不是一个好的选择,因为我相信将重载的 operator<< 添加到 std 命名空间会导致未定义的行为。
不应该在允许编译器找到定义operator<<
之前定义 my s吗?#include
该技术似乎适用于以下示例,改编自同一个 clang 页面。
c++ - find() 使用重载的 operator==
我尝试使用重载运算符==() 在向量中查找元素。但是,如果type1
在以下代码中使用,则输出为 1 和 0(未找到)。Usingtype2
给出 1 和 1。环境是 Xubuntu 12.04 和 g++ 版本 4.6.3。
c++ - 我需要对 Stroustrup 关于 ADL 的新书中的这个例子进行一些澄清
我在 Stroustrup 书(第 4 版)第 396 页和第 397 页中给出的参数相关查找(ADL)示例下方重现:
上面的评论说的是正确的(我已经测试过了),但这似乎与作者在下一段中所说的不一致:
在标准中,依赖于参数的查找规则是根据关联的命名空间来表述的(iso §3.4.2)。基本上:
- 如果参数是类成员,则关联的命名空间是类本身(包括其基类)和类的封闭命名空间。
- 如果参数是命名空间的成员,则关联的命名空间是封闭的命名空间。
- 如果参数是内置类型,则没有关联的命名空间。
在示例中x
,具有 typeN::S
的 不是 class 的成员D
,也不是其 base的成员Base
。但它是namespace N
. 根据上面的第二个项目符号,该函数N::f(S)
应该是被调用的函数,而不是Base::f()
.
上面的结果似乎也与标准中第 3.4.2p2 段中的第二个项目符号不一致,其中说:
如果 T 是类类型(包括联合),则其关联的类是:类本身;它所属的类别(如有的话);及其直接和间接基类。其关联名称空间是其关联类是其成员的名称空间。此外,如果 T 是类模板特化,则其关联的命名空间和类还包括: 与为模板类型参数(不包括模板模板参数)提供的模板实参类型相关联的命名空间和类;任何模板模板参数都是其成员的命名空间;以及用作模板模板参数的任何成员模板是其成员的类。