JuanPablo
JuanPablo

Reputation: 24754

object in a set iterator

I can get a method of a class in a set iterator ?

#include <iostream>
#include <string>
#include <set>
class student{
  public:
     student(std::string n){
        name=n;
     }
     void print(){
        std::cout << name << std::endl;
     }
     bool operator < (const student & s1){ return true;}
     bool operator = (const student & s1){ return true;}
  private:
     std::string name;
};
int main(){
  std::set<student> studs;
  studs.insert(student("name01"));
  studs.insert(student("name02"));
  std::set<student>::iterator it;
  for(it = studs.begin(); it != studs.end(); it++)
      (*it).print() ;
}

I get this error

students.cpp: In function ‘int main()’:  
students.cpp:22: error: passing ‘const student’ as ‘this’ argument of ‘void student::print()’ discards qualifiers
/usr/include/c++/4.2.1/bits/stl_function.h: In member function ‘bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = student]’:
/usr/include/c++/4.2.1/bits/stl_tree.h:982:   instantiated from ‘std::pair<typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(const _Val&) [with _Key = student, _Val = student, _KeyOfValue = std::_Identity<student>, _Compare = std::less<student>, _Alloc = std::allocator<student>]’
/usr/include/c++/4.2.1/bits/stl_set.h:307:   instantiated from ‘std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(const _Key&) [with _Key = student, _Compare = std::less<student>, _Alloc = std::allocator<student>]’
students.cpp:18:   instantiated from here
/usr/include/c++/4.2.1/bits/stl_function.h:227: error: passing ‘const student’ as ‘this’ argument of ‘bool student::operator<(const student&)’ discards qualifiers

with

     bool operator<(const student & s1) const { return true;}  
     bool operator==(const student & s1) const { return true;}  

now work!! O_o',

#include <iostream>
#include <string>
#include <set>
class student{
  public:
     student(std::string n){
        name=n;
     }
     void print() const {
        std::cout << name << std::endl;
     }
     bool operator<(const student & s1) const { return true;}
     bool operator==(const student & s1) const { return true;}
  private:
     std::string name;
};
int main(){
  std::set<student> studs;
  studs.insert(student("name01"));
  studs.insert(student("name02"));
  std::set<student>::iterator it;
  for(it = studs.begin(); it != studs.end(); it++)
      it->print() ;
}

Upvotes: 2

Views: 8659

Answers (5)

Uday Hiwarale
Uday Hiwarale

Reputation: 4157

#include <iostream>
#include <set>
using namespace std;
class Boxer{
    public:
        string name;
        int strength;
};
struct Comp{
    bool operator()(const Boxer& a, const Boxer& b){
        return a.strength > b.strength;
    }
};
int main(){
    Boxer boxer[3];
    boxer[0].name="uday", boxer[0].strength=23;
    boxer[1].name="manoj", boxer[1].strength=33;
    boxer[2].name="rajiv", boxer[2].strength=13;

    set< Boxer, Comp> s;
    s.insert(boxer[0]);
    s.insert(boxer[1]);
    s.insert(boxer[2]);
    set< Boxer, Comp>::iterator it = s.begin();
    Boxer b = *it;
    cout<<b.name;
    //result is Manoj

    return 0;
}

Upvotes: 0

Chris Hopman
Chris Hopman

Reputation: 2102

  1. You want operator==, not operator=.

  2. Your operator< definition violates the requirements of std::set, and is inconsistent with your operator<. That is, according to your operator<, nothing is equivalent, but according to your operator==, everything is equal. Operator< should define a irreflexive, transitive, and asymmetric (for non-equivalent values) relation.

  3. Objects in a set are necessarily const, and so to call a function on such an object that function must be declared with the const qualifier. Specifically, print() should be declared void print() const.

  4. Similarly, operator< should be declared with the const qualifier. std::set requires that operator< can be called with const objects. Another valid option would be to make operator< a non-member function and to take both objects by value (bad) or const reference (good).

  5. While not required in your example, operator== should also be declared with the const qualifier.

Upvotes: 2

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361342

Write your print() function like this:

void print() const //<---- note this 'const'
{
        std::cout << name << std::endl;
}

Now your code should work now. :-)

By the way, such functions with const keyword appearing on the right side, are called const member function, as they cannot change any member-data of the class.

See this FAQ: [18.10] What is a "const member function"?

Upvotes: 1

Charles Salvia
Charles Salvia

Reputation: 53289

You need to add a const qualifer to your print member function:

void print() const
{
  std::cout << name << std::endl;
}

Objects in an std::set are necessarily const, since they are used as keys. When an object (or reference) is constant, you can only call member functions of that object which are declared with the const qualifier.

You also want const qualifiers on both the == and < operator overload functions. (And don't forget to change = to == as pointed out in the comments.)

Upvotes: 5

Steve Townsend
Steve Townsend

Reputation: 54138

Yes, though it->print() is more intuitive.

A naive world-view is that iterators are a bit like pointers. There is more to it than that, as explained here.

The most obvious form of iterator is a pointer: A pointer can point to elements in an array, and can iterate through them using the increment operator (++). But other forms of iterators exist. For example, each container type (such as a vector) has a specific iterator type designed to iterate through its elements in an efficient way.

Upvotes: 3

Related Questions