Лямбда-выражение для find_if

0

В настоящее время я пытаюсь найти элемент в векторе 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

У моей лямбды exp есть два параметра. Как компилятор узнает, как он должен заменить их правильными значениями.

  • 2
    Что вы ожидаете std::find_if в качестве значений?
Теги:

4 ответа

3

Ваша транскрипция сообщения об ошибке пропускает самую интересную часть: сообщение об ошибке!

Тем не менее проблема кажется очевидной: для функции find_if нужен только один параметр, поэтому вам нужно find_if name, что для []:

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

Эта справочная страница достаточно хорошо описывает лямбды.

  • 0
    Можете ли вы объяснить, что означает [& name]? если у меня есть функция с более чем одним аргументом. я должен написать [& name, & other]
  • 0
    @ user2975699: Конечно: это список захвата. Это означает, что name из внешней области будет доступно внутри лямбды с тем же именем. Вы можете сделать [name] чтобы скопировать значение в лямбду, или [&name] чтобы получить его по ссылке, то есть без копирования. Если вы захватываете по ссылке, будьте осторожны, чтобы ваша лямбда не проживала дольше, чем зафиксированное значение.
Показать ещё 1 комментарий
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);
  • 0
    Но если у меня есть унарный предикат, как я могу сравнить две вещи?
  • 0
    @ user2975699 Просто используйте std::find , как показано выше.
Показать ещё 1 комментарий
1

Вам не нужно использовать std::find_if. Достаточно использовать std::find

Изменить инструкцию thsi

 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 );

EDIT: Мне очень жаль. Я не видел, что вы определили вектор как

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

В этом случае вам действительно нужно использовать std::find_if с выражением лямбда

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;

Проблема в том, что вы представили запутанный пример кода. :)

0

to find_if вы должны передать "предикат", то есть функцию, принимающую один единственный параметр и возвращающий true/false.

Замена лямбды

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

должен работать так, как вы ожидаете.

Тем не менее, как указано другим, вы можете просто передать строку, чтобы find вместо предиката find_if потому что find использует operator== любом случае.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню