4

很久以前,我注意到在 Visual C++ 10 中,当至少一个参数是 lambda 时,ADL 会失败。

std::vector<float> vec;
for_each(begin(vec), end(vec), [](float) {}); 

以上无法在 VC++10 和 11 (beta) 上编译(通过 ADL 找到开始和结束)。当我将 lambda 函数转换为常规的自由函数时,事情会按预期工作。

我曾经在 Herb Sutters 博客上问过一次,还阅读了 msdn connect 上的一些帖子,通常的答案是:这是一个错误,我们还没有实现 lambdas 的最新标准,这在当时是可以理解的。事情还没有成熟。在 MS connect 上,也有令人不安的评论,即下一个版本(即 vc 11)将无法解决此问题。

我的问题是,这段代码是否可以在 C++11 标准下工作?我不能完全弄清楚。当我使用 lambdas 时,我真的必须在我的 for_each 和其他算法前面加上 std:: 吗?我怀疑这种行为在 vc++11 发布后不会改变。

4

2 回答 2

15

该标准并不能保证您想要它..

考虑到以下内容,我们可以很容易地意识到,在与您帖子中提供的示例类似的情况下,无法保证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 Range Access23.3.6.1/2 类模板向量(或任何其他模板 STL 容器)。

  • [](){}- Lambda 表达式

    lambda 是实现定义的类型,标准中没有任何内容说明生成的对象将属于命名空间 std下的类型。

    只要它符合标准制定的其他规则,它几乎可以存在于任何它想要的地方。



太长; 没读过

std::begin// yield的类型不能保证在命名空间 stdstd::end下,因此 ADL不能保证启动。a lambda-expression

于 2012-03-28T02:02:22.113 回答
1

这是完全有效的代码。任何无错误的编译器都可以编译它。但是由于 MSVC 有 bug 无法通过 ADL 搜索函数,那么也许你不应该依赖 ADL 而是通过std::帮助编译器找到函数来限定它。

于 2012-03-28T01:32:01.633 回答