Как использовать std:: find/std:: find_if с вектором объектов пользовательского класса?
У меня есть класс, представляющий пользователя с именем Nick
, и я хочу использовать std::find_if
на нем, где я хочу найти, есть ли в элементе userlist объект с тем же именем пользователя, в котором я проходил. Я сделал несколько попытки попытаться создать новый объект Nick
для имени пользователя, который я хочу проверить и перегрузить == operator
, а затем попытаться использовать find/find_if
для объекта:
std::vector<Nick> userlist;
std::string username = "Nicholas";
if (std::find(userlist.begin(), userlist.end(), new Nick(username, false)) != userlist.end())) {
std::cout << "found";
}
Я перегрузил == operator
, поэтому сравнение Nick == Nick2 должно работать, но функция возвращает error C2678: binary '==' : no operator found which takes a left-hand operand of type 'Nick' (or there is no acceptable conversion)
.
Вот мой класс Nick для справки:
class Nick {
private:
Nick() {
username = interest = email = "";
is_op = false;
};
public:
std::string username;
std::string interest;
std::string email;
bool is_op;
Nick(std::string d_username, std::string d_interest, std::string d_email, bool d_is_op) {
Nick();
username = d_username;
interest = d_interest;
email = d_email;
is_op = d_is_op;
};
Nick(std::string d_username, bool d_is_op) {
Nick();
username = d_username;
is_op = d_is_op;
};
friend bool operator== (Nick &n1, Nick &n2) {
return (n1.username == n2.username);
};
friend bool operator!= (Nick &n1, Nick &n2) {
return !(n1 == n2);
};
};
Ответы
Ответ 1
Вы должны определить operator == с двумя объектами вне вашего класса, как функцию инструмента, а не членом.
Затем, чтобы сделать его другом, просто поместите объявление функции внутри класса.
попробуйте что-то вроде этого:
class Nick {
public:
friend bool operator== ( const Nick &n1, const Nick &n2);
};
bool operator== ( const Nick &n1, const Nick &n2)
{
return n1.username == n2.username;
}
Также ваша находка должна выглядеть так:
std::find(userlist.begin(), userlist.end(), Nick(username, false) );
Не нужно "нового".
Ответ 2
Если вы используете С++ 0X, вы можете использовать простое лямбда-выражение
std::string username = "Nicholas";
std::find_if(userlist.begin(), userlist.end(), [username](Nick const& n){
return n.username == username;
})
Ответ 3
Я знаю, что вы хотели перегрузить оператор ==
, но то же самое можно легко сделать с помощью предиката:
struct UsernameIs {
UsernameIs( string s ) : toFind(s) { }
bool operator() (const Nick &n)
{ return n.username == toFind; }
string toFind;
};
int main()
{
vector<Nick> vn(10);
string nameToFind = "something";
find_if(vn.begin(), vn.end(), UsernameIs(nameToFind));
}
Обратите внимание, что в С++ 0x вы можете сделать то же самое с выражением лямбда гораздо более кратко.
Ответ 4
Вы передаете указатель на функцию поиска. Отбросьте новое:
std::find(userlist.begin(), userlist.end(), Nick(username, false))
Кроме того, ваши операторы должны принимать свои аргументы по ссылке const, они не изменяют их.
bool operator== (const Nick &n1, const Nick &n2)
Ответ 5
Я замечаю, что вы пытаетесь вызвать один конструктор из другого таким образом:
Nick(std::string d_username, bool d_is_op) {
Nick();
...
Ну, извините, но это не сработает. Строка Nick()
просто создает временную и не влияет на this
. Переадресация конструктора возможна только в С++ 0x (предстоящий стандарт)
Что касается вашей проблемы - этот вопрос, заданный пару дней назад о binary_search, охватывает те же самые основания. Главный ответ просто потрясающий.
Мистическое ограничение на std:: binary_search
НТН.
P.S. В идеале это должен был быть комментарий, но он слишком многословный
Ответ 6
Вы можете использовать boost:: bind
std::find_if( userlist.begin(), userlist.end(),
boost::bind( & Nick::isFound,
_1 ) );
просто выполните bool Nick:: isFound()
Вы также можете передать критерии
std::find_if( userlist.begin(), userlist.end(),
boost::bind( & Nick::compare,
_1,
nick ) );
реализовать
bool Nick::compare( const Nick & nick )
{
return this->username == nick.username;
}