当存在lambda参数时,ADL将失败

ADL fails when there are lambda arguments?

本文关键字:ADL 失败 存在 lambda 参数      更新时间:2023-10-16

不久前,我注意到在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::来帮助编译器找到函数。