【问题标题】:Lambda Expression for find_iffind_if 的 Lambda 表达式
【发布时间】:2014-02-24 02:32:28
【问题描述】:

我目前正在尝试在向量 V 中查找一个元素。 但我得到了很多错误。

bool VNS::remove(const HostName& name){ ^ 在 /usr/lib/gcc/x86_64-pc-cygwin/4.8.2/include/c++/algorithm:62:0 包含的文件中, 来自 vns.cc:2:.....

 bool VNS::remove(const HostName& name){
        auto it=find_if(v.begin(),v.end(),[](const HostName& a, const HostName& b){return a==b;});
        //code that will remove the elem.
        if(it!=v.end()){
            return true;
        }else{
            return false;
        }
    }
HeaderFile:
class VNS:public NameServerInterface{
    public:
        /*
         * Insert a name/address pair. Does not check if the name
         * or address already exists.
         */
        virtual void insert(const HostName&, const IPAddress&);

        /*
         * Remove the pair with the specified host name. Returns true
         * if the host name existed and the pair was removed, false
         * otherwise.
         */
        virtual bool remove(const HostName&);

        /*
         * Find the IP address for the specified host name. Returns
         * NON_EXISTING_ADDRESS if the host name wasn't in the name
         * server.
         */
        virtual IPAddress lookup(const HostName&) const;

    private:
        std::vector<std::pair<HostName,IPAddress> > v;
};

界面:

/*
 * Interface NameServerInterface -- all name server implementations must
 * implement this interface.
 */
#ifndef NAME_SERVER_INTERFACE_H
#define NAME_SERVER_INTERFACE_H

#include <string>

using HostName = std::string;
using IPAddress = unsigned int;
const IPAddress NON_EXISTING_ADDRESS = 0;

class NameServerInterface {
public:
    virtual ~NameServerInterface() = default;

    /*
     * Insert a name/address pair. Does not check if the name
     * or address already exists.
     */
    virtual void insert(const HostName&, const IPAddress&) = 0;

    /*
     * Remove the pair with the specified host name. Returns true
     * if the host name existed and the pair was removed, false
     * otherwise.
     */
    virtual bool remove(const HostName&) = 0;

    /*
     * Find the IP address for the specified host name. Returns
     * NON_EXISTING_ADDRESS if the host name wasn't in the name
     * server.
     */
    virtual IPAddress lookup(const HostName&) const = 0;
};

#endif

我的 lambda exp 有两个参数。编译器如何知道它应该如何用正确的值替换它们。

【问题讨论】:

  • 您希望std::find_if 作为值传入什么?

标签: c++


【解决方案1】:

您的错误消息转录遗漏了最有趣的部分:错误消息!

不过,问题似乎很明显:find_if 函数只需要一个参数,所以你需要捕获name,这就是[] 的用途:

auto it=find_if(v.begin(),v.end(),
    [&name](const HostName& a){return a==name;});

reference page 很好地解释了 lambda。

【讨论】:

  • 你能解释一下 [&name] 是什么意思吗?如果我有一个具有多个 arg 的函数。我应该写 [&name, &other]
  • @user2975699:当然:这是捕获列表。这意味着来自外部作用域的name 将在 lambda 内部可用,具有相同的名称。您可以使用[name] 将值复制到 lambda 中,或者使用[&amp;name] 通过引用获取它,即无需复制它。如果您通过引用捕获,请注意您的 lambda 不会比捕获的值长。
【解决方案2】:

std::find_if 需要 一元 谓词。你正在传递一个二进制

auto it=find_if(v.begin(),v.end(),
                [](const HostName& a, const HostName& b){return a==b;});

这行不通。看起来这是你真正想要的:

auto it = std::find(v.begin(),v.end(), name);

【讨论】:

  • 但是如果我有一元谓词,我怎么能比较两件事呢?
  • @user2975699,你基本上是在做 std::find 循环中已经做的事情。它使用== 将它所在的对象与它正在寻找的对象进行比较。如果它有帮助,您可以查看 std::find here 的示例实现,看看它对自己有什么作用。
【解决方案3】:

您无需使用std::find_if。用std::find就够了

改变这条语句

 auto it=find_if(v.begin(),v.end(),[](const HostName& a, const HostName& b){return a==b;});

 auto it=find( v.begin(),v.end(), name );

编辑:对不起。我没有看到您将向量定义为

std::vector<std::pair<HostName,IPAddress> > v;

在这种情况下,您确实需要将 std::find_if 与 lambda 表达式一起使用

auto it=find_if( v.begin(), v.end(), 
                [&]( const std::pair<HostName,IPAddress>& a) { return a.first == name; } );

同样作为成员函数remove 有返回类型bool 我建议使用算法std::any_of 而不是std::find_if

例如

bool VNS::remove( const HostName &name )
{
   return any_of( v.begin(), v.end(), 
                  [&]( const std::pair<HostName,IPAddress>& a) { return a.first == name; } );    
}

虽然如果你需要函数内部的目标迭代器,那么确实最好使用std::find_if

还要考虑到,如果你确实从向量中删除了一个元素,那么之后你可能不会再写了

    if(it!=v.end()){
        return true;
    }else{
        return false;
    }

有效的代码将是

bool found = it != v.end();
if ( found )
{
   // removing the element
}

return found;

问题是您提供了一个令人困惑的代码示例。:)

【讨论】:

    【解决方案4】:

    find_if 你应该传递一个“谓词”,即一个函数接受一个参数并返回true/false

    将您的 lambda 替换为

    [&](const HostName& a){return a==name;}
    

    应该如您所愿。

    正如其他说明的那样,您可以将字符串传递给find,而不是将谓词传递给find_if,因为find 无论如何都使用operator==

    【讨论】:

      猜你喜欢
      • 2013-04-28
      • 1970-01-01
      • 2013-07-02
      • 1970-01-01
      • 1970-01-01
      • 2022-11-12
      • 2019-08-04
      • 1970-01-01
      • 2014-04-08
      相关资源
      最近更新 更多