Ошибка компиляции с std :: find при попытке получить определенные пользователем объекты из std :: vector - PullRequest
0 голосов
/ 19 марта 2019

Я пытаюсь создать базовое приложение, которое моделирует активность «заметок».Это будет содержать функции для добавления заметок и удаления заметок.Ниже приведен код.В функции deleteNote я нахожу заголовок в векторе Notes, который задается в качестве входного аргумента с помощью метода std :: find.API-интерфейс std :: find вызывает ошибки компиляции.Ниже приведен код.

```#include <iostream>
#include <vector>
#include <utility>
#include <tuple>
#include <algorithm>

using InitializerTags = std::initializer_list<std::string>;
using TupleObject = std::tuple<std::string, std::string, std::string>;
class Note
{

public:
    TupleObject m_tags;

    Note(std::string title, std::string text, std::string tags){
        std::cout<< "parameterized Constructor"<< std::endl;
        m_tags  =  std::make_tuple(title, text, tags);
    }

    /*Note(const Note& rhs){
        std:: cout << "copy constructor"<< std::endl;
        m_tags = rhs.m_tags;
    }*/

    Note(Note&& rhs){
        std::cout<< "move constructor"<< std::endl;
        m_tags = rhs.m_tags;
    }

    Note& operator=(Note&& rhs){
        std::cout << "move assignment"<< std::endl;
        if(this != &rhs){
            m_tags = rhs.m_tags;
        }
        return *this;
    }

    Note() = delete;
    Note(const Note& rhs) = delete;
    Note& operator=(const Note& rhs) = delete;

    ~Note(){

    }
};

class Storyboard
{
private:
    std::vector <Note> m_notes;
public:

    /*Storyboard(){
        m_notes.reserve(1);
    }*/

    void addNote(std::string title, std::string text, std::string tags)
    {
        std::cout << "inside addNote"<< std::endl;
        m_notes.emplace_back(title, text, tags);
    }

    void deleteNote(std::string title)
    {
        for(auto& x: m_notes){
            if(std::get<0>(x.m_tags) == title){
                m_notes.erase(std::find(m_notes.begin(),m_notes.end(), x));
            }
        }
    }


    void print()
    {
        std::cout << "Inside print"<< std::endl;
        for(auto& x : m_notes){
            std::cout << std::get<0>(x.m_tags)<< " ";
            std::cout << std::get<1>(x.m_tags)<< " ";
            std::cout << std::get<2>(x.m_tags)<< " ";
            std::cout << std::endl;
        }
    }
};



Below is the error.

In file included from /usr/include/c++/5/bits/stl_algobase.h:71:0,
                 from /usr/include/c++/5/bits/char_traits.h:39,
                 from /usr/include/c++/5/ios:40,
                 from /usr/include/c++/5/ostream:38,
                 from /usr/include/c++/5/iostream:39,
                 from StoryBoard.cpp:1:
/usr/include/c++/5/bits/predefined_ops.h: In instantiation of ‘bool __gnu_cxx::__ops::_Iter_equals_val<_Value>::operator()(_Iterator) [with _Iterator = __gnu_cxx::__normal_iterator<Note*, std::vector<Note> >; _Value = const Note]’:
/usr/include/c++/5/bits/stl_algo.h:120:14:   required from ‘_RandomAccessIterator std::__find_if(_RandomAccessIterator, _RandomAccessIterator, _Predicate, std::random_access_iterator_tag) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Note*, std::vector<Note> >; _Predicate = __gnu_cxx::__ops::_Iter_equals_val<const Note>]’
/usr/include/c++/5/bits/stl_algo.h:161:23:   required from ‘_Iterator std::__find_if(_Iterator, _Iterator, _Predicate) [with _Iterator = __gnu_cxx::__normal_iterator<Note*, std::vector<Note> >; _Predicate = __gnu_cxx::__ops::_Iter_equals_val<const Note>]’
/usr/include/c++/5/bits/stl_algo.h:3790:28:   required from ‘_IIter std::find(_IIter, _IIter, const _Tp&) [with _IIter = __gnu_cxx::__normal_iterator<Note*, std::vector<Note> >; _Tp = Note]’
StoryBoard.cpp:67:73:   required from here
/usr/include/c++/5/bits/predefined_ops.h:194:17: error: no match for ‘operator==’ (operand types are ‘Note’ and ‘const Note’)
  { return *__it == _M_value; }


I Checked the files in which the error occurred. 
The problem has occurred with the signature of std::find which is 
std::find(_IIter, _IIter, const _Tp&)

The 3rd input arguement is being taken as **const reference** and this is being compared with non const reference in predefined_ops.h:194.

I am trying to understand what in my code led to this situation.
Also trying to figure out the fix.
Any help which would clear my understanding would be appreciated.

1 Ответ

0 голосов
/ 19 марта 2019

В

std::find(m_notes.begin(),m_notes.end(), x)
Алгоритм

std::find пытается сравнить элемент из m_notes с x, но вы не предоставили operator==, который это делает, поэтому появляется сообщение об ошибке. Поскольку вы стираете элементы на основе заголовка, вы можете написать:

class Note
{
public:
    //...

    // comparison operator as member function
    bool operator == (const Note& theOther) const {
        // compare titles
        return std::get<0>(m_tags) == std::get<0>(theOther.m_tags);
    }
    //...
};

тогда код компилируется, но, вероятно, он потерпит крах. Вы используете циклический цикл for, который проверяет итератор vector::end, но он может быть недействительным при вызове vector::erase. Посмотрите, как реализован диапазон и как используется end.

Теперь вы перебираете все элементы в векторе, и если заголовок соответствует title, вы звоните find, чтобы найти элемент, который нужно удалить. Это излишне, вы можете переходить на вектор с помощью итератора, а когда заголовок совпадает, просто вызовите алгоритм erase для текущего итератора без повторной итерации вектора с помощью find:

Перепишите deleteNote примерно так:

void deleteNote(std::string title)
{
    for (auto it = m_notes.begin(); it != m_notes.end(); )
    {
        if(std::get<0>(it->m_tags) == title)
            it = m_notes.erase(it); // returns the first element past the removed one
        else 
            ++it;
    }
}

Если вы хотите переместить rhs.m_tags; в ctor перемещения и переместить оператор присваивания, вам нужно привести rhs.m_tags к Rreference - m_tags = std::move(rhs.m_tags);.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...