简体   繁体   中英

Lambda Expression for find_if

I am currently trying to find an element in vector V. but i get a lot of errors.

bool VNS::remove(const HostName& name){ ^ In file included from /usr/lib/gcc/x86_64-pc-cygwin/4.8.2/include/c++/algorithm:62:0, from 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:

/*
 * 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

My lambda exp has two parameters. How will the compiler know how it should replace them with correct values.

Your error message transcription misses the most interesting part: the error message!

Nevertheless, the problem seems obvious: the find_if function only needs one parameter, so you need to capture the name , that's what the [] are for:

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

This reference page explains the lambdas quite well.

std::find_if expects unary predicate. You are passing it a binary one:

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

This cannot work. It looks like this is what you really want:

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

You need not to use std::find_if . It is enough to use std::find

Change thsi statement

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

to

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

EDIT : I am sorry. I did not see that you defined the vector as

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

In this case you indeed need to use std::find_if with a lambda expression

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

Also as member function remove has return type bool I would advice to use algorithm std::any_of instead of std::find_if

For example

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

Though if you need the target iterator inside the function then indeed it is better to use std::find_if

Also take into account that if you indeed removed an element from the vector you may not write after that

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

The valid code will be

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

return found;

The problem is that you provided a confusing example of code.:)

to find_if you should pass a "predicate", ie a function taking one single parameter and returning true / false .

Replacing your lambda with

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

should work as you expect.

That said as other noted however you can just pass the string to find instead of a predicate to find_if because find uses operator== anyway.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM