Reputation: 465
I have to implement my own list with the stl for my data structures class here is the code I have.
Playlist.h
#ifndef PLAYLIST_H
#define PLAYLIST_H
#include <iostream>
using std::ostream;
#include <list>
using std::list;
class Song;
class Playlist
{
public:
void append(const char* name, const char* artist);
list<Song>::iterator find(const char* name) const;
void delete_song(const char* name);
void print(ostream& out) const;
private:
list<Song> plist;
};
ostream& operator << (ostream& out, const Playlist& playlist);
#endif /* PLAYLIST_H */
ostream& operator << (ostream& out, const Playlist& playlist);
#endif /* PLAYLIST_H */
Playlist.cpp
#include <iostream>
using std::ostream;
using std::endl;
#include <cstring>
#include "Song.h"
#include "Playlist.h"
void Playlist::append(const char* name, const char* artist)
{
Song song(name, artist);
plist.push_back(song);
}
list<Song>::iterator Playlist::find(const char* name) const
{
list<Song>::iterator itr = plist.begin(); // error occurs here
while(itr != plist.end() && strcmp(itr->get_name(), name) == 0)
{
itr++;
}
return itr;
}
void Playlist::delete_song(const char* name)
{
list<Song>::iterator itr = find(name);
if (itr != plist.end())
plist.erase(itr);
}
void Playlist::print(ostream& out) const
{
list<Song>::iterator itr = plist.begin(); // error occurs here
while (itr != plist.end())
{
out << *itr << endl;
itr++;
}
}
ostream& operator << (ostream& out, const Playlist& playlist)
{
playlist.print(out);
return out;
}
When I try to compile this I get:
error: conversion from ‘std::list::const_iterator {aka std::_List_const_iterator}’ to non-scalar type ‘std::list::iterator {aka std::_List_iterator}’ requested
in both places marked in the code.
Upvotes: 1
Views: 5120
Reputation: 320491
Well, it is what the error message says it is.
It was you who declared Playlist::print
as a const
method of the class. This immediately means that inside that method all class members now have const
types. Your plist
will have type const list<Song>
inside Playlist::print
. Methods begin()
/end()
of const containers return const_iterator
for those containers. You cannot initialize/assign iterator
with an const_iterator
. That's what the compiler is telling you.
Either switch to const_iterator
inside those methods, or stop declaring these methods const
.
In case of Playlist::print
the answer is obvious: just switch to const_iterator
.
In case of Playlist::find
it might be a different story. It is a matter of your intent. If you just switch to const_iterator
inside Playlist::find
, you will have to return const_iterator
from it. Does that work for you? But if you want to be able to modify the playlist from outside through the returned iterator, you will typically have to implement two versions of Playlist::find
: a const one, returning const_iterator
, and a non-const one, returning iterator
.
Upvotes: 0
Reputation: 4203
Use list<Song>::const_iterator itr = plist.begin();
You are declaring the method as const
which marks the object on which it is being executed as const. So you should not be allowed to change the members. But regular iterator
allows changing the object it references. For this purpose, const_iterator
was created - it works similarly, but you do not have ability to change the object it is pointing to.
EDIT 2
You could remove const
from the method and it would compile, but it is a bad idea - your method is lookup, it does not alter the object contents, and so the interface should indicate that explicitly.
Upvotes: 1
Reputation: 64223
In both places, you are invoking the const version of List::begin()
, which return List::const_iterator
.
list<Song>::const_iterator itr = plist.begin();
should fix the problem, but then you need the signature of your methods to return const_iterator.
Upvotes: 0
Reputation: 70929
Method void Playlist::print(ostream& out) const
is designated const. Thus plist is const
and so plist.begin()
returns a const_iterator
. You will either have to remove the const from the method, use const_cast(worst solution), or simply use a const_iterator to iterate over the list(best option).
Upvotes: 2
Reputation: 8950
Your method is marked const (i.e it doesn't have the right to modify the instance variables), but you access to your list with an iterator which is not marked const ;and by returning it for instance you could modify the instance variable and break the "const" keyword of the method.
Hope that Im clear
Upvotes: 1
Reputation: 1021
if you're in a const method, you can only call the begin method returning a const_iterator, so you should use those instead of simple iterators.
Upvotes: 0