C++ lambda 语法

Posted

技术标签:

【中文标题】C++ lambda 语法【英文标题】:C++ lambda syntax 【发布时间】:2019-08-10 02:45:15 【问题描述】:

我有一个函数可以搜索迭代器向量,如果它的名称与作为参数传递的字符串匹配,则返回迭代器。

koalaGraph::PVertex lookUpByName(std::string Name, std::vector<koalaGraph::PVertex>& Vertices) 

    for (size_t i = 0; i < Vertices.size(); i++) 

        if(Vertices[i]->info.name == Name) 
            return Vertices[i];
    

我的问题是如何将其实现为 lambda,以将其与 std::find_if 结合使用?

我正在尝试这个:

std::vector<koalaGraph::PVertex> V;
std::string Name;
std::find_if(V.begin(), V.end(), [&Name]() return Name == V->info.name;)

但它说V

不能在 lambda 主体中引用封闭函数局部变量,除非它在捕获列表中。

【问题讨论】:

No return 如果没有找到? 【参考方案1】:

find_if 会将向量的元素传递给您的 lambda。这意味着你需要

std::find_if(V.begin(), V.end(), [&Name](auto const& V) return Name == V->info.name;)

因此 lambda 主体中的 V 是向量的元素,而不是向量本身。


理想情况下,您应该给它一个不同于V 的名称,这样您就可以将向量和局部变量分开,就像

std::find_if(V.begin(), V.end(), [&Name](auto const& element) return Name == elememt->info.name;)

所以现在很明显,您正在处理向量的一个元素,而不是向量本身。

【讨论】:

【参考方案2】:

首先,V-&gt;info.name 在 lambda 内部或外部的格式不正确。

发送到算法std::find_if 的函数对象必须是一元函数。它必须将当前元素作为参数进行检查。

auto found = std::find_if(
    V.begin(), V.end(), 
    [&Name](koalaGraph::PVertex const& item_to_check) 
        return Name == item_to_check->info.name;
    
);

found 的类型是已找到元素的迭代器。如果没有找到,则返回V.end()

如果您使用 C++14 或更高版本,您甚至可以使用通用 lambda:

auto found = std::find_if(
    V.begin(), V.end(), 
    [&Name](auto const& item_to_check) 
        return Name == item_to_check->info.name;
    
);

【讨论】:

V-&gt;info.name 是有效的语法。它只是不会进行类型检查,因为向量不会重载-&gt; It just won't typecheck since vectors don't overload -&gt; 所以......它不会编译?在不重载 operator-&gt; 的类型对象上使用 -&gt; 是一种无效语法 并非所有编译错误都是语法错误。见syntax vs. semantics。 @SilvioMayolo 你链接我的答案说语义是程序的含义,通常在它的运行时行为中。我引用的代码只是格式错误,还没有语义。或者我没有正确理解这个概念【参考方案3】:

std::find_if 的谓词将依次接收对范围内每个元素的引用。你需要:

std::find_if(
    V.begin(), V.end(),
    [&Name](koalaGraph::PVertex const &v)  return Name == v->info.name; 
);

【讨论】:

【参考方案4】:

获取 V 作为 lambda 的参数。

std::find_if(V.begin(), V.end(), [&amp;Name](type&amp; V) return Name == V-&gt;info.name;)

【讨论】:

【参考方案5】:

使用const auto &amp; 在 lambda 表达式中访问向量中的各个元素。由于向量是左值,因此 auto 将被推导出为const vector&lt;PVertex&gt; &amp;。然后,您可以使用std::distance 查找该对象在向量中的元素位置。

struct PVertex

    std::string name;
;

int main()

    std::vector<PVertex> V = "foo","bar","cat","dog";

    std::string Name = "cat";

    auto found = std::find_if(std::begin(V), std::end(V), [&Name](const auto &v)return (Name == v.name););

    std::cout<< "found at: V["<<std::distance(std::begin(V),found)<<"]" <<std::endl;

结果是:

found at: V[2]

示例:https://rextester.com/IYNA58046

【讨论】:

以上是关于C++ lambda 语法的主要内容,如果未能解决你的问题,请参考以下文章

c++ lambda表达式与函数对象

c++的lambda使用注意事项,可能导致的崩溃问题分析

聊聊 C++ 和 C# 中的 lambda 玩法

c++的lambda使用注意事项,可能导致的崩溃问题分析

Lambda表达式

c++ 11 lambda表达式