adam
adam

Reputation: 465

Stl List Iterator Error

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

Answers (6)

AnT stands with Russia
AnT stands with Russia

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

gt6989b
gt6989b

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

BЈовић
BЈовић

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

Ivaylo Strandjev
Ivaylo Strandjev

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

Thomas
Thomas

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

Julien Lopez
Julien Lopez

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

Related Questions