somehow I can't use stable_partition algorithm on
vector<pair<Class, string>>.
I can re-organize the code to get what I want, but for me (as I am new to C++) it's more "WHY" and not "HOW" question. will be glad if you clarify this behavior:
First, class Date (you can omit it and come look at it later):
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;
class Date {
public:
Date(int new_year, int new_month, int new_day) {
year = new_year; month = new_month; day = new_day;
}
int GetYear() const {return year;}
int GetMonth() const {return month;}
int GetDay() const {return day;}
private:
int year, month, day;
};
bool operator<(const Date& lhs, const Date& rhs) {
return vector<int>{lhs.GetYear(), lhs.GetMonth(), lhs.GetDay()} <
vector<int>{rhs.GetYear(), rhs.GetMonth(), rhs.GetDay()};
}
bool operator==(const Date& lhs, const Date& rhs) {
return vector<int>{lhs.GetYear(), lhs.GetMonth(), lhs.GetDay()} ==
vector<int>{rhs.GetYear(), rhs.GetMonth(), rhs.GetDay()};
}
SO THIS IS THE CLASS WITH THE TROUBLE:
class Database {
public:
void Add(const Date& date, const string event){
storage.push_back(make_pair(date, event));
set_dates.insert(date);
}
void Print(ostream& s) const{
for(const auto& date : set_dates) {
// TROUBLE IS HERE:
auto it = stable_partition(begin(storage), end(storage),
[date](const pair<Date, string> p){
return p.first == date;
});
};
}
private:
vector<pair<Date, string>> storage;
set<Date> set_dates;
};
When compiled, it returns a lot of problems of same kind:
I've tried the same code on vector<pair<int, string>> (used stable_partition with lambda {return p.first == _int; } and it worked.
Would appreciate your help
The std::stable_partition function is supposed to modify the vector. However, you are calling it in a const member function, so storage is const there. This can't work.
Solution: Don't make Print const, or use std::stable_partition on a copy of storage. Neither is a great solution, so you should probably rethink your design.
You need to define overloading operator= for Date class as well. It will work if you do that stuff.
class Date {
public:
Date(int new_year, int new_month, int new_day) {
year = new_year; month = new_month; day = new_day;
}
// Need to define overloading operator=
Date& operator=(const Date& rhs)
{
}
int GetYear() const {return year;}
int GetMonth() const {return month;}
int GetDay() const {return day;}
private:
int year, month, day;
};
Related
I saw this answer.
https://stackoverflow.com/a/47317853/8106257
But, I don't satisfying logical const.
Is there any other way to sort custom class object with const member variable?
I was firstly thought that how about using move constructor but it didn't work.
#include <iostream>
#include <vector>
#include <algorithm>
class City
{
private:
const int _cost;
const int _customer;
public:
City(int cost, int customer) : _cost(cost), _customer(customer)
{
}
City(const City&& city) : _cost(city._cost), _customer(city._customer)
{
}
City& operator=(const City& city) = delete;
bool operator<(const City& city) const
{
return false;
}
};
struct Comparator
{
bool operator()(const City& l, const City& r) { return l < r; }
};
int main()
{
int C, N;
std::cin >> C >> N;
std::vector<City> vec;
for(int i = 0; i < N; ++i)
{
int cost, customer;
std::cin >> cost >> customer;
vec.emplace_back(cost, customer);
}
sort(vec.begin(), vec.end(), Comparator());
}
You can't sort your std::vector because the std::sort uses move assignment and move construction to sort the elements. If you take a look here: sort
you will find:
Type requirements:
The type of dereferenced RandomIt must meet the requirements of MoveAssignable and MoveConstructible.
You can't assign nor move assign as your members are const.
This makes it impossible to use std::sort in your case.
Not possible prior to c++20 but now is. Note there is no need for move semantics since the types are all POD types where move semantics don't do anything.
#include <iostream>
#include <vector>
#include <algorithm>
class City
{
private:
const int _cost;
const int _customer;
public:
City(int cost, int customer) : _cost(cost), _customer(customer){}
City& operator=(const City& city)
{
if (this!= &city)
std::construct_at(this, city); // no destruction needed since trivially destructable
return *this;
}
// change as required to the sorting reqs
bool operator<(const City& city) const
{
return _customer < city._customer;
}
};
struct Comparator
{
bool operator()(const City& l, const City& r) { return l < r; }
};
int main()
{
int C, N;
std::cin >> C >> N;
std::vector<City> vec;
for (int i = 0; i < N; ++i)
{
int cost, customer;
std::cin >> cost >> customer;
vec.emplace_back(cost, customer);
}
sort(vec.begin(), vec.end(), Comparator());
}
compiler explorer
https://godbolt.org/z/hE43z7763
#include <string>
#include <tuple>
#include <stdexcept>
using namespace std;
class Date
{
public:
Date() {};
Date(int new_year, int new_month, int new_day)
{
year = new_year;
if ((new_month < 1) || (new_month > 12))
{
throw runtime_error("Month value is invalid: " + to_string(new_month));
}
month = new_month;
if ((new_day < 1) || (new_day > 31))
{
throw runtime_error("Day value is invalid: " + to_string(new_day));
}
day = new_day;
}
int GetYear() const
{
return year;
}
int GetMonth() const
{
return month;
}
int GetDay() const
{
return day;
}
private:
int year;
int month;
int day;
};
bool operator < (const Date &lhs, const Date &rhs)
{
auto lhs = tie(lhs.GetYear(), lhs.GetMonth(), lhs.GetDay());
auto rhs = tie(rhs.GetYear(), rhs.GetMonth(), rhs.GetDay());
return lhs < rhs;
}
I'm trying to create a class for storing the date (year, month, day). In order to use this class in a map, I want to overload the comparison operator. Unfortunately, the code above does not work. The compiler gives me an error
error: cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'|
The error apparently occurs in tie function. Once I change it to make_tuple everything compiles and works. I also checked that if I declared variables year, month and day as public I could write something like
auto lhs = tie(lhs.year, lhs.month, lhs.day);
and this would also work.
I don't understand why. Does anyone have ideas?
Your member functions return copy of the members(aka temprory rvalue), and std::tie has argument list, which try to bind by non-cost lvalue ref.
template< class... Types >
constexpr std::tuple<Types&...> tie( Types&... args ) noexcept;
// ^^^^^^^^^^^^^^^^
This is simply not possible as per standard, hence the error!
The std::make_tuple on the other hand has forwarding reference. Therefore, no issues.
template< class... Types >
std::tuple<VTypes...> make_tuple( Types&&... args );
// ^^^^^^^^^^^^^^^^
When the members are public, they became lvalues.
I would suggest, make the operator< friend of the class instead.
class Date
{
public:
// .... other code
friend bool operator<(const Date& lhs, const Date& rhs) noexcept
{
return std::tie(lhs.year, lhs.month, lhs.day) < std::tie(rhs.year, rhs.month, rhs.day);
}
private:
int year;
int month;
int day;
};
The entire purpose of std::tie is to create a tuple of lvalue references. Your member functions return int which aren't lvalues, and so you get an error.
Making the member variables public and using them directly as arguments to tie works because variables are lvalues.
Trying to overload the == operator, want to compare the hour, min, sec variables, but they're declared private and we've been told we're not allowed to adjust the header file. How do I access them in my code that is overloading the == operator? I also can't access them as h, m, s as they're called in the setTime method.
// using _TIMEX_H_ since _TIME_H_ seems to be used by some C++ systems
#ifndef _TIMEX_H_
#define _TIMEX_H_
using namespace std;
#include <iostream>
class Time
{ public:
Time();
Time(int h, int m = 0, int s = 0);
void setTime(int, int, int);
Time operator+(unsigned int) const;
Time& operator+=(unsigned int);
Time& operator++(); // postfix version
Time operator++(int); // prefix version
// new member functions that you have to implement
Time operator-(unsigned int) const;
Time& operator-=(unsigned int);
Time& operator--(); // postfix version
Time operator--(int); // prefix version
bool operator==(const Time&) const;
bool operator<(const Time&) const;
bool operator>(const Time&) const;
private:
int hour, min, sec;
friend ostream& operator<<(ostream&, const Time&);
// new friend functions that you have to implement
friend bool operator<=(const Time&, const Time&);
friend bool operator>=(const Time&, const Time&);
friend bool operator!=(const Time&, const Time&);
friend unsigned int operator-(const Time&, const Time&);
};
#endif
.cpp file
using namespace std;
#include <iostream>
#include <iomanip>
#include "Time.h"
Time::Time()
{ hour = min = sec = 0;
}
Time::Time(int h, int m, int s)
{ setTime(h, m, s);
}
void Time::setTime(int h, int m, int s)
{ hour = (h>=0 && h<24) ? h : 0;
min = (m>=0 && m<60) ? m : 0;
sec = (s>=0 && s<60) ? s : 0;
}
Time operator==(Time &t1, Time &t2)
{
return (t1.hour==t2.hour);
}
The == operator you're supposed to implement is a member function, so you should define
bool Time::operator==(const Time& t) const
{
return hour == t.hour && min == t.min && sec == t.sec;
}
Here is a trick:
bool operator==(Time &t1, Time &t2)
{
return !(t1 != t2);
}
bool operator!=(const Time& t1, const Time& t2)
{
return t1.hour != t2.hour || t1.min != t2.min || t1.sec != t2.sec;
}
You can't access your private fields in your operator== function. But since your operator!= is defined as friend, you can do it there.
#include <iostream>
using namespace std;
class DrivingLicence
{
protected:
Person owner;
char * type;
Date validity;
int id;
static int cid;
public:
DrivingLicence(Person &o,char* t,Date &d);
DrivingLicence(Person &o,char* t);
DrivingLicence(const DrivingLicence & other);
Date getValidity() const;
int checkValidity() const;
void print() const;
bool operator== (const DrivingLicence& o) const;
void operator +(const int num);
const DrivingLicence& operator= (const DrivingLicence& other);
~DrivingLicence();
};
class Person
{
private:
int id;
char* name;
Date birthday;
public:
Person(char* name,int id1,Date &d);
Person(const Person &other);
~Person();
Date getBirthday() const;
const Person& operator= (const Person & other);
void print() const;
};
class Date
{
int day;
int month;
int year;
public:
Date (int day,int month,int year);
~Date();
const Date& operator=(const Date& other);
bool operator==(const Date & other);
void print() const;
int getYear()const;
int getMonth()const;
int getDay()const;
};
up above are my classes,
i need to initialize both constructors in the DrivingLicence class (not the copy cons), however i cant manage to do that.
can someone please help me with the syntax for this question??
what i mean is :
#include <NameOfHeaderFile>
DrivingLicense::DrivingLicense( Person &o,char* t,Date &d ) : //Code here for 1stconstructor
{
}
DrivingLicense::DrivingLicense( Person &o,char* t ) ://Code here for 2nd constructor
{
}
i don't know how to initialize the values
I assume this is a header file, however usually there is only 1 class per .h file. So you need to create a file called DrivingLicence.cpp.
In this file write:
#include <NameOfHeaderFile>
DrivingLicense::DrivingLicense( Person &o,char* t,Date &d )
{
//Code here for 1stconstructor
}
DrivingLicense::DrivingLicense( Person &o,char* t )
{
//Code here for 2nd constructor
}
Is this what you are asking???
If I have understood your problem, you want a DriverLicence constructor that
also initializes the person inside the DriverLicense instance.
If so, you only have to add this overload to your class:
DriverLicense::DriverLicense(
// Data for Person
char *person_name, int person_id, Date day_birth,
// Data for Driver licence
char *t, Date d)
{
owner = Person(person_name, person_id, day_birth);
// More code here initializing DeriverLicence members.
}
Remember of course add it to your class:
class DriverLicence
{
public:
// ...
DriverLicense::DriverLicense(char *, int, Date, char *t, Date d);
// ...
}
A couple of Advice:
You're working with C++, use std:string instead char*
Don't abuse of passing arguments as references. Some times this is not
the best to do.
If you're trying to initialize the members of your DrivingLicense class with the arguments passed to the constructor, you can do that in your initializer list.
It's would be wise to put these definitions in a cpp. Also note the changes to types and constness or the arguments I'm providing.
DrivingLicense::DrivingLicense(const Person &o, const std::string& t, const Date &d )
: owner(o)
, type(t)
, validity(d)
{ }
DrivingLicense::DrivingLicense(const Person &o, const std::string& t)
: owner(o)
, type(t)
{ } // Note that 'validity' here is default constructed.
include "header.h"
int DrivingLicence::cid =1000;
DrivingLicence::DrivingLicence(Person &o, char* t, Date &d ): owner(o), type(t), validity(d)
{
}
DrivingLicence::DrivingLicence(Person &o,char* t) :owner(o), type(t),validity(8,10,2024){}
this is what i meant.
thanks for all the answers.
I want to construct two priority queue that has different compare method(there are two reverse priority methods named cmp1 and cmp2)
My program can't go through the compiler check.Why does such error happen and is there any better solution?
#include <iostream>
#include <queue>
#include <string>
using namespace std;
struct item
{
string name;
string sex;
string id;
double score;
friend istream& operator >> (istream &is,item& data)
{
is>>data.name>>data.sex>>data.id>>data.score;
}
/*friend bool operator < (item& a,item& b)
{
return a.score<b.score;
}*/
};
struct cmp1{
operator bool()(item& x,item& y)
{
return x.score>y.score;
}
};
struct cmp2
{
operator bool()(item& x,item& y)
{
return x.score<y.score;
}
};
int main()
{
priority_queue<item,vector<item>,cmp1> boys;
priority_queue<item,vector<item>,cmp2>girls;
item temp;
int num;
cin>>num>>temp;
for(int i=0;i<num;i++)
{
if(temp.sex=="M")
boys.push(temp);
else
girls.push(temp);
}
return 0;
}
I'm going to take a wild guess at the problem.... your comparison functors are incorrect. Instead of overloading operator bool, you need to overload the function call operator, i.e.
struct cmp1{
bool operator()(const item& x, const item& y)
{
return x.score>y.score;
}
};
struct cmp2
{
bool operator()(const item& x, const item& y)
{
return x.score<y.score;
}
};
(Perhaps this was what you intended, but just got the syntax a little wrong?)
Actually, I think the best way to do it is to use std::less and std::greater. If you have overloaded operator< and operator> for your class, you can do it like this:
std::priority_queue<item, std::vector<item>, std::greater<item>> boys;
std::priority_queue<item, std::vector<item>, std::less<item>> girls;
That way you don't have to write the functor. Don't forget to #include <functional>.
Also, don't forget that the operators have to be overloaded taking const ref arguments (you can also take them by value, but that's not usually a good idea), and as const methods, like in:
bool operator<(const item& i) const {
return value < i.value;
}
bool operator>(const item& i) const {
return value > i.value;
}
Change your operator functions to this:
struct cmp1{
bool operator()(item& x,item& y)
{
return x.score>y.score;
}
};
struct cmp2
{
bool operator()(item& x,item& y)
{
return x.score<y.score;
}
};
You have defined the methods in the comparison classes wrong.
Try the following code:
struct cmp1{
bool operator()(item& x,item& y)
{
return x.score>y.score;
}
};
You have defined the methods as operator bool() ....
Also it is nice to add const to the parameters, as const item& x for showing that you won't change their values, as well a const at the end of the function definition:
bool operator()(const item& x, const item& y) const {...}
for showing that you won't change the member fields too.
I will write the third correct version of the predcate
struct cmp1
{
bool operator()( const item &x, const item &y ) const
{
return x.score > y.score;
}
};
struct cmp2
{
bool operator()( const item &x, const item &y ) const
{
return x.score < y.score;
}
};