当存在lambda参数时,ADL将失败
ADL fails when there are lambda arguments?
不久前,我注意到在Visual C++10中,当至少有一个参数是lambda时,ADL会失败。
std::vector<float> vec;
for_each(begin(vec), end(vec), [](float) {});
以上内容无法在VC++10和11(测试版)上编译(通过ADL找到开始和结束)。当我把lambda函数转换成一个正则的自由函数时,一切都如预期的那样。
我在Herb Sutters博客上问过一次,也读过一些关于msdn connect的帖子,通常的答案是:这是一个错误,我们还没有实现lambdas的最新标准,这在当时是可以理解的。事情还没有完全成熟。在MS connect上,也有令人不安的评论称,这将不会在下一个版本(即vc 11)中得到解决。
我的问题是,这个代码是否期望在C++11标准下工作?我想不通。当我使用lambdas时,我真的必须在for_each和其他算法前面加std::吗?我怀疑在vc++11发布后,这种行为不会改变。
标准不能保证您想要的东西。
考虑到以下内容,我们可以很容易地意识到,没有什么可以保证ADL在类似于您帖子中提供的例子的情况下工作。
-
std::begin (c)
/std::end (c)
标准中的功能描述如下:
template <class C> auto begin(C& c) -> decltype(c.begin()); template <class C> auto end(C& c) -> decltype(c.end());
尽管
Container< ... >::iterator
(它是c.begin ()
的返回类型)是一个实现定义的类型。有关该问题的更多信息,请访问24.5.6范围访问和23.3.6.1/2类模板向量(或任何其他模板STL容器)
-
[](){}
-Lambda表达式lambda是实现定义的类型,标准中没有任何内容表明生成的对象将属于命名空间std下的类型。
只要它符合标准制定的其他规则,它几乎可以存在于任何它想要的地方。
太长;未读取
std::begin
/std::end
/a lambda-expression
产生的类型不能保证在命名空间std下,因此ADL不能保证生效。
这是非常有效的代码。任何没有bug的编译器都可以编译它。但由于MSVC有bug,因此无法通过ADL搜索函数,因此您可能不应该依赖ADL,而应该使用std::
来帮助编译器找到函数。
- 如果没有malloc,链表实现将失败
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- 视图中的参数推导失败:take_while
- 链接到自行创建的dll失败
- 带有特殊路径部分的"std::filesystem::weakly_canonical"失败
- GetShortPathName在网络驱动器上使用中文文件夹时失败
- gcc和c++17的过载解析失败
- 为什么使用 P/Invoke 调用 dll 时,某些计算机中的 LoadLibrary 失败?
- 在WSL:configure_file上对config_file的每次调用都失败:配置文件时出现问题
- 使用 GCC 卸载的 OpenMP 卸载失败,并出现"Ptx assembly aborted due to errors"
- 使用cmake从源代码构建MySQL连接器/C++失败(与以前的声明冲突)
- 链接阶段在Ubuntu上失败,但在MacOS上失败
- 从父数组测试用例构造二叉树失败
- LibGit2 SSH身份验证失败
- 如何让LLDB在成功时退出,在失败时等待
- VS2017,C++包含目录与附加包含目录,子文件夹包含失败-但为什么
- 生成MRPT库时cmake配置失败
- ADL 失败(或未完成?)具有附加(非推导)模板参数的函数
- 当存在lambda参数时,ADL将失败