我正在尝试创建一个对“便签”活动进行建模的基本应用程序。这将包含添加注释和删除注释的功能。下面是代码。在deleteNote函数中,我正在使用std :: find方法作为输入参数给出的Notes向量中找到标题。 std :: find API抛出编译错误。下面是代码。
```#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.
答案 0 :(得分:0)
在
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
时可能无效。 See how range-for is implemented and how end
is used.
现在,您要遍历vector中的所有元素,如果标题与title
相匹配,则您正在调用find
来查找要删除的元素。实在是太过分了,您可以使用迭代器遍历vector,而当标题匹配时,只需为当前迭代器调用erase
算法,而无需通过find
重新迭代vector:
将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;
}
}
如果要在移动ctor和移动赋值运算符中移动rhs.m_tags;
,则需要将 rhs.m_tags 强制转换为Rreference-m_tags = std::move(rhs.m_tags);
。