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() ;
}
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.)
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.
You want operator==, not operator=.
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.
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.
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).
While not required in your example, operator== should also be declared with the const qualifier.
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"?
#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;
}
Related
This question already has answers here:
Const map element access
(4 answers)
Closed 1 year ago.
I have some struct like bellow to get static const map:
struct SupportedPorts{
static std::map<std::string, std::string> init()
{
std::map<std::string, std::string> port;
port["COM1"] = "ttySO1";
port["COM2"] = "ttySO2";
port["USB"] = "ttyUSB0";
return port;
}
static const std::map<std::string, std::string> supported_ports;
};
But I have problem when I trying get some value by key. In cpp file of class Exmaple:
#include "Example.h"
const std::map<std::string, std::string> SupportedPorts::supported_ports = SupportedPorts::init();
Example::Example(){
std::cout << SupportedPorts::supported_ports['COM1'];
}
I get error like bellow:
note: initializing argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
error: conversion to non-const reference type ‘std::map<std::basic_string<char>, std::basic_string<char> >::key_type&& {aka class std::basic_string<char>&&}’ from rvalue of type ‘std::basic_string<char>’ [-fpermissive]
std::cout << SupportedPorts::supported_ports['COM1'];
^
(null):0: confused by earlier errors, bailing out
The operator [] is declared for the class template std::map the following way
T& operator[](const key_type& x);
T& operator[](key_type&& x);
That is the the operator returns a non-constant reference that may not be done for a constant object. And the operator may be called only for a non-constant object because it is declared without the qualifier const.
Instead use the function at declared like
T& at(const key_type& x);
const T& at(const key_type& x) const;
Also instead of a string literal you are using a multibyte character literal in this statement
std::cout << SupportedPorts::supported_ports['COM1'];
Write
std::cout << SupportedPorts::supported_ports.at( "COM1" );
Here is a demonstrative program.
#include <iostream>
#include <string>
#include <map>
int main()
{
const std::map<std::string, std::string> supported_ports =
{
{ "COM1", "ttySO1" }, { "COM2", "ttySO2" }, { "USB", "ttyUSB0" }
};
std::cout << supported_ports.at( "COM1" ) << '\n';
return 0;
}
The program output is
ttySO1
I've got a template class containing a priority queue of other classes, I need to use the priority overloader to call the individual class overloaders to compare based on the individual classes preferences (in this case it's age, in another class it could be price.
I've got absolutely no doubt that I've implemented the operator overloading incorrect so would appreciate the advice.
For example
#include <iostream>
#include <queue>
#include <string>
using namespace std;
class Animal {
public:
Animal();
Animal(string t, int a);
int get_age()const;
bool operator< ( Animal& b) const;
void display()const;
private:
string type;
double age;
};
void Animal::display() const
{
cout << "Type: " << type << " Age: " << age;
}
int Animal::get_age() const
{
return age;
}
Animal::Animal(){}
Animal::Animal(string t, int a)
{
type = t;
age = a;
}
bool Animal::operator< ( Animal& b) const
{
return b.get_age();
}
template<typename T>
class Collection {
public:
Collection();
Collection(string n, string d);
void add_item(const T& c);
private:
priority_queue <T> pets;
string name; // Name of the collection
string description; // Descriptions of the collection
};
template<typename T>
Collection<T>::Collection(){}
template<typename T>
Collection<T>::Collection(string n, string d)
{
name = n;
description = d;
}
template<typename T>
bool operator<(const T& one, const T& two)
{
return one.operator<(two);
}
template<typename T>
void Collection<T>::add_item(const T& c)
{
pets.push(c);
}
int main(){
Animal p1("Dog", 10);
Animal p2("Cat", 5);
Animal p3("Turtle", 24);
Collection<Animal> P("Pets", "My Pets");
P.add_item(p1);
P.add_item(p2);
P.add_item(p3);
cout << endl;
return 0;
}
I get this error and I'm not sure what I need to do to fix it. I've got to keep the class overloader as the single variable (Animal& b).
task.cpp: In instantiation of 'bool operator<(const T&, const T&)
[with T = Animal]':
c:\mingw-4.7.1\bin../lib/gcc/mingw32/4.7.1/include/c++/bits/stl_function.h:237:22:
required from 'bool std::less<_Tp>::operator()(const _Tp&, const _Tp&)
const [with _Tp = Animal]'
c:\mingw-4.7.1\bin../lib/gcc/mingw32/4.7.1/include/c++/bits/stl_heap.h:310:4: required from 'void std::__adjust_heap(_RandomAccessIterator,
_Distance, _Distance, _Tp, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator > >; _Distance = int; _Tp = Animal; _Compare =
std::less]'
c:\mingw-4.7.1\bin../lib/gcc/mingw32/4.7.1/include/c++/bits/stl_heap.h:442:4: required from 'void std::make_heap(_RandomAccessIterator,
_RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator > >; _Compare = std::less]'
c:\mingw-4.7.1\bin../lib/gcc/mingw32/4.7.1/include/c++/bits/stl_queue.h:393:9: required from 'std::priority_queue<_Tp, _Sequence,
_Compare>::priority_queue(const _Compare&, const _Sequence&) [with _Tp = Animal; _Sequence = std::vector >; _Compare = std::less]' task.cpp:57:45: required from 'Collection::Collection(std::string, std::string) [with T = Animal;
std::string = std::basic_string]' task.cpp:79:43: required
from here task.cpp:66:30: error: no matching function for call to
'Animal::operator<(const Animal&) const' task.cpp:66:30: note:
candidate is: task.cpp:36:6: note: bool Animal::operator<(Animal&)
const task.cpp:36:6: note: no known conversion for argument 1 from
'const Animal' to 'Animal&' task.cpp: In function 'bool
operator<(const T&, const T&) [with T = Animal]':
Your comparison
bool Animal::operator< ( Animal& b) const
{
return b.get_age(); // returns true always unless age == 0
}
is no comparison and it should take a const parameter. You should have something like
bool Animal::operator< (const Animal& b) const
// ^----------------------- const !
{
return get_age() < b.get_age();
}
Btw you dont need to use a member operator< for the priority queue. Especially if you want to sort objects in different ways I would recommend to not use it, but pass a lambda to the priority_queue. See eg here for an example.
Both of your overloads of < are problematic
bool Animal::operator< ( Animal& b) const
the Animal should also be const. You also need to compare both parameters, otherwise things (such as your priority_queue) that expect < to provide an ordering will have undefined behaviour.
You don't use anything non-public from Animal, so I suggest you change it to
bool operator< (const Animal & lhs, const Animal & rhs)
{ return lhs.get_age() < rhs.get_age(); }
This has the benefit of treating both sides identically, rather than one being implicit.
template<typename T>
bool operator<(const T& one, const T& two)
{
return one.operator<(two);
}
This template matches all types and is entirely superfluous. a < b can call either a member or a free operator <. Just delete this template.
I have vector<FPGA*> current_generation_, which I'd like to sort by FPGA member fitness_ using the sort_members function. Applicable code follows:
bool sort_members (FPGA* fpga_first, FPGA* fpga_second) {
return (fpga_first->fitness() < fpga_second->fitness());
};
fpga.hpp
#include <vector>
class FPGA {
public:
explicit FPGA(int input_gates, int output_gates, int normal_gates);
const int fitness();
protected:
int fitness_;
};
fpga.cpp
FPGA::FPGA() {
this->fitness_ = 0;
}
const int FPGA::fitness() {
return this->fitness_;
}
implementation:
std::sort(this->current_generation_.begin(), this->current_generation_.end(), sort_members);
errors:
/usr/include/c++/4.9/bits/stl_algo.h: In instantiation of ‘void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = std::__detail::_Node_iterator<std::pair<const int, FPGA*>, false, false>; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(FPGA*, FPGA*)>]’:
/usr/include/c++/4.9/bits/stl_algo.h:4717:78: required from ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = std::__detail::_Node_iterator<std::pair<const int, FPGA*>, false, false>; _Compare = bool (*)(FPGA*, FPGA*)]’
/usr/include/c++/4.9/bits/stl_algo.h:1968:22: error: no match for ‘operator-’ (operand types are ‘std::__detail::_Node_iterator<std::pair<const int, FPGA*>, false, false>’ and ‘std::__detail::_Node_iterator<std::pair<const int, FPGA*>, false, false>’)
std::__lg(__last - __first) * 2,
The remainder of the total error string is huge, but I believe is mostly what the compiler believes(falsely) are candidates. I'm not extremely familiar with c++, and a compiler error of this magnitude and complexity is confusing to me.
I can provide more context if needed. Thanks!
EDIT: A dash.
EDIT EDIT: I screwed up, and was trying to sort the wrong member. Hooray.
The only error that I see is this>current_generation_.end() instead that ->.
In addition you should consider declaring your compare fuction as accepting two const FPGA* instead that just FPGA*. This will force you to declare fitness() as const int fitness() const but it makes sense to have it const.
Mind that since you are using C++11 you can directly use a lambda:
std::sort(data.begin(), data.end(), [](const FPGA* f1, const FPGA* f2) { ... });
You also have the choice to overload operator< directly:
class FPGA {
...
bool operator<(const FPGA* other) const { return fitness_ < other->fitness_; }
}
std::sort(data.begin(), data.end());
This could be useful if it doesn't make sense to have other criteria to compare two FPGA instances since you add some semantics to the object itself.
With the below code, I am trying to update the values in a set but its not compiling when i try to compile .
It's giving me the error at the bottom, can you please help ?
What wrong I am doing here?
#include < iostream >
#include < set >
using namespace std;
class A
{
public:
int a,b;
bool operator()(A a1,A a2)
{
return true;
}
A(int a ,int b)
{
this.a=a;
this.b=b;
}
};
void print_set(const std::set<A>&st) const
{
std::set<A>::iterator it;
std::cout<<"\nvalues in set";
for(it=st.begin();it!=st.end();it++)
{
std::cout<<"\na="<<it->a<<"b="<<it->b;
}
}
int main ()
{
std::set<A> s;
for ( int i=0;i<5;i++)
{
s.insert(A(i,i+1));
}
print_set(s);
std::set<A>::iterator it;
for(it=s.begin();it!=s.end();it++)
{
A tmp=*it;
s.erase(it);
tmp.a=10;
tmp.b=20;
s.insert(tmp);
std::cout<<"\ninserting tmp "<<tmp.a<<" "<<tmp.b;
}
print_set(s);
return 0;
}
I am getting an error like this :
/usr/include/c++/4.6/bits/stl_function.h: In member function ‘bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = A]’:
/usr/include/c++/4.6/bits/stl_tree.h:1277:4: instantiated from ‘std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(const _Val&) [with _Key = A, _Val = A, _KeyOfValue = std::_Identity<A>, _Compare = std::less<A>, _Alloc = std::allocator<A>]’
A few issues in your code, see below comments:
A(int a ,int b)
{
//this.a=a;
//this.b=b;
this->a = a; // this pointer should be accessed by this->
this->b = b;
}
// to store element in std::set, it must follow strict weak ordering rule.
// by default, operator< need to be defined
bool operator<(const A& lhs, const A& rhs)
{
return lhs.a < rhs.a;
}
// print_set is not a member function, can't have trailing const after function name
void print_set(const std::set<A>&st) // const
I wrote a piece of code and used map and vector but it shows me something I can't get. I'll be thankful if someone help me in this way and correct my code or give me some hints.
The code is:
// For each node in N, calculate the reachability, i.e., the
// number of nodes in N2 which are not yet covered by at
// least one node in the MPR set, and which are reachable
// through this 1-hop neighbor
std::map<int, std::vector<const NeighborTuple *> > reachability;
std::set<int> rs;
for (NeighborSet::iterator it = N.begin(); it != N.end(); it++)
{
NeighborTuple const &nb_tuple = *it;
int r = 0;
for (TwoHopNeighborSet::iterator it2 = N2.begin (); it2 != N2.end (); it2++)
{
TwoHopNeighborTuple const &nb2hop_tuple = *it2;
if (nb_tuple.neighborMainAddr == nb2hop_tuple.neighborMainAddr)
r++;
}
rs.insert (r);
reachability[r].push_back (&nb_tuple);
}
/*******************************************************************************/
//for keepping exposition of a node
std::map<Vector, std::vector<const NeighborTuple *> > position;
std::set<Vector> pos;
for (NeighborSet::iterator it = N.begin(); it != N.end(); it++)
{
NeighborTuple nb_tuple = *it;
Vector exposition;
pos.insert (exposition);
position[exposition].push_back (&nb_tuple);
}
and the errors are for this line: position[exposition].push_back (&nb_tuple);
and the errors are:
/usr/include/c++/4.1.2/bits/stl_function.h: In member function ‘bool std::less<_
Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = ns3::Vector3D]’:
/usr/include/c++/4.1.2/bits/stl_map.h:347: instantiated from ‘_Tp& std::map<_K
ey, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = ns3::Vector3D, _Tp = std::vector<const ns3::olsr::NeighborTuple*, std::allocator<const ns3::olsr::NeighborTuple*> >, _Compare = std::less<ns3::Vector3D>, _Alloc = std::allocator<std::pair<const ns3::Vector3D, std::vector<const ns3::olsr::NeighborTuple*, std::allocator<const ns3::olsr::NeighborTuple*> > > >]’
../src/routing/olsr/olsr-routing-protocol.cc:853: instantiated from here
/usr/include/c++/4.1.2/bits/stl_function.h:227: error: no match for ‘operator<’ in ‘__x < __y’
debug/ns3/ipv6-address.h:432: note: candidates are: bool ns3::operator<(const ns3::Ipv6Address&, const ns3::Ipv6Address&)
debug/ns3/nstime.h:475: note: bool ns3::operator<(const ns3::Time&, const ns3::Time&)
debug/ns3/ipv4-address.h:305: note: bool ns3::operator<(const ns3::Ipv4Address&, const ns3::Ipv4Address&)
debug/ns3/address.h:231: note: bool ns3::operator<(const ns3::Address&, const ns3::Address&)
debug/ns3/type-id.h:376: note: bool ns3::operator<(ns3::TypeId, ns3::TypeId)
Thanks in advance.
Bahar
std::map is a sorted container of pairs. As such, keys in the map must have operator <() defined. Make sure Vector has the less-than operator defined.
For example:
class Vector {
int len, ang;
friend bool operator<(const Vector&, const Vector&);
};
bool operator<(const Vector& v1, const Vector& v2)
{
return true_if_v1_is_less_than_v2(); // you define what "less than" means
}
Of course, there other ways to do this. You may make operator< a member function. Or you may have the two member data public and the operator a non-member, non-friend function. Or you may define operator< in an anonymous namespace, to enhance information hiding. Or you may use a comparator other than operator<.
You declared the position object as followed : std::map<Vector, std::vector<const NeighborTuple *> > position;
And you are trying to push NeighborTuple * inside...
Try using const NeighborTuple *
I notice that you seem to have a pushback line that compiles and a line that does not.
The difference might be that you have a const in the first case
NeighborTuple const &nb_tuple = *it;