C++ compiler has contradictory complaints about overloading the << operator - c++

By the way, I am using eclipse and g++ on arch linux (I ran pacman -Syu less than a week ago, so everything is up to date).
Eclipse produces an error every time I try to compile this:
#ifndef DATE_HPP_
#define DATE_HPP_
using namespace std;
class Date {
public:
int Year;
char Month;
char Day;
char HH;
char MM;
char ss;
Date();
/*
* Overloaded Operator Functions
*/
//Assignments
Date operator=(Date input);
//Comparisons
bool operator==(Date& rhs);
bool operator!=(Date& rhs);
bool operator<(Date& rhs);
bool operator>(Date& rhs);
bool operator<=(Date& rhs);
bool operator>=(Date& rhs);
//Conversion
operator char*();
operator std::string();
ostream& operator<<(ostream& os, const Date& date); //TROUBLE LINE
};
#endif /* DATE_HPP_ */
Eclipse shows a message on the operator<< declaration saying it must only have a single argument. Yet, when I declare it like this:
ostream& operator<<(const Date& date);
It complains that it must have two. What am I doing wrong?

The two-argument overload of the operator must be a non-member function. Either move it out of the class definition, or add friend to it to make it a non-member friend function, whichever makes more sense.
The one-argument overload is not useful, since it is used when the object instance is the left operand.

friend ostream& operator<<(ostream& os, const Date& date);
Also you can add some consts to your code. For example..
bool operator==(const Date& rhs) const;
I also suggest you make all integers int, even if they will only take a small value (such as month) unless there is a technical reason you need them to be chars.

Related

Cannot access friend classes private variable in overloading "<<" and ">>" (Using multiple files)

I was just learning about friend classes and overloading operators in C++ where I came upon an issue where I cannot access the private variables in the friend class. I'm almost sure this has to do with the fact we were required to have each file separate (Header, .cpp and main). Need some fresh eyes.
// Contents of Percent.h
#ifndef PERCENT_H
#define PERCENT_H
#pragma once
class Percent
{
// friend const Percent operator >>(Percent& first, Percent& second);
public:
friend bool operator ==(const Percent& first,
const Percent& second);
friend bool operator <(const Percent& first,
const Percent& second);
Percent();
friend istream& operator >>(istream& inputStream,
Percent& aPercent);
friend ostream& operator <<(ostream& outputStream,
const Percent& aPercent);
//There will be other members and friends.
private:
int value;
};
// Contents of Percent.cpp
#include <iostream>
#include "Percent.h"
using namespace std;
istream& operator >>(istream& inputStream,
Percent& aPercent)
{
char percentSign;
ERROR HERE - Cannot access value
inputStream >> aPercent.value;
inputStream >> percentSign;
return inputStream;
}
ostream& operator <<(ostream& outputStream,
const Percent& aPercent)
{
outputStream << aPercent.value << '%';
return outputStream;
}
#endif // !PERCENT_H
// Main.cpp
not written yet

friend function has no access to private class members

I am still new to C++ and as part of an assignment I have written a class that needs an overload of the stream extraction operator '>>' for file stream extraction in order to make things a bit easier, so says the instructions. I have declared and defined 2 overloads for both operators, one oveload for iostream objects and one overload for fstream object. Now, everything is fine until i get to the definition of '>>' for file stream objects, apparently that function has no access to the private (or protected) member of the class of which it is a friend of.
Here is my code, i thank you all in advance:
stock.h
#ifndef STOCK_H
#define STOCK_H
#include<iostream>
#include<fstream>
class Stock_Type
{
friend std::ostream& operator<<(std::ostream&, const Stock_Type&);
friend std::istream& operator>>(std::istream&, Stock_Type&);
friend std::ofstream& operator<<(std::ofstream&, const Stock_Type&);
friend std::ifstream& operator>>(std::ofstream&, Stock_Type&);
public:
//constructor overloads-----------------------------------------------------------------------------------------------------
Stock_Type(){};
Stock_Type(std::string sym, double a, double b, double c, double d, double e, int f, double g) :
stock_symbol(sym), opening_price(a), closing_price(b), high_price(c), low_price(d), prev_close(e), volume(f), percent_gain(g) {}
//default destructor--------------------------------------------------------------------------------------------------------
~Stock_Type(){};
//accessor functions--------------------------------------------------------------------------------------------------------
void set_Symbol(std::string x){stock_symbol = x;}
void set_Closing_Price(double x){closing_price = x;}
void set_High_Price(double x){high_price = x;}
void set_Low_Price(double x){low_price = x;}
void set_Prev_Close(double x){prev_close = x;}
void set_Volume(int x){volume = x;}
std::string get_Stock_Smybol(){return stock_symbol;}
double get_Opening_Price(){return opening_price;}
double get_Closing_Price(){return closing_price;}
double get_High_Price(){return high_price;}
double get_Low_Price(){return low_price;}
double get_Prev_Close(){return prev_close;}
int get_Volume(){return volume;}
double get_Percent_Gain_Loss(){return get_Closing_Price() - get_Opening_Price();}
//operations on Stock_Type-------------------------------------------------------------------------------------------------------
//operator functions--------------------------------------------------------------------------------------------------------------
bool operator==(const Stock_Type&)const;
bool operator!=(const Stock_Type&)const;
bool operator<(const Stock_Type&) const;
bool operator<=(const Stock_Type&)const;
bool operator>(const Stock_Type&)const;
bool operator>=(const Stock_Type&)const;
friend std::ostream& operator<<(std::ostream&, const Stock_Type&);
friend std::istream& operator>>(std::istream&, Stock_Type&);
const Stock_Type& operator=(const Stock_Type &right_operand);
Stock_Type& operator[](int elem);
const Stock_Type& operator[](int elem) const;
private:
std::string stock_symbol;//record data1
double opening_price, closing_price, high_price, low_price, prev_close;//record data2
int volume;//record data3
double percent_gain;//record data 4
Stock_Type *stock_pointer;
int array_size;
};
#endif
stock.cpp, i will only include the function for which an error is generated
std::ifstream& operator>>(std::ifstream& if_obj, Stock_Type& stock_obj)
{
if_obj >> stock_obj.stock_symbol
>> stock_obj.opening_price
>> stock_obj.closing_price
>> stock_obj.high_price
>> stock_obj.low_price
>> stock_obj.prev_close
>> stock_obj.volume
>> stock_obj.percent_gain;
return if_obj;
}
the error is that for all the attributes that are listed are "inaccessible"
I'd like to finish this assignment as I'd like to move on to another one that is due on exception handling.
Thank you all in advance, once again.
i apologize, I believe that the signatures in the definition and implementation were different, as pointed out by a previous comment, i declared a friend function twice and there i saw my error, i did not change the code after copy/pasting it. For all future readers: MAKE SURE DECALRATION SIGNATURES MATCH IMPLEMENTATION SIGNATURES!
There is a
friend std::ifstream& operator>>(std::ofstream&, Stock_Type&);
but you have access problems in
std::ifstream& operator>>(std::ifstream& if_obj, Stock_Type& stock_obj)
Adding another friend should help.
friend std::ifstream& operator>>(std::ifstream& if_obj, Stock_Type& stock_obj);
Actually, you might prefer to edit the existing friend, it very much looks like a typo or other kind of trivial error.

C++ container - set and object

I have following class.
class Student {
//Parameterized constructor.
private:
int rollNo;
char* name;
float marks;
}
I have a set<Student> students. When I insert a student object in set, how can I sepcify that two objects are same. E.g. I am considering two objects same if their rollNo is same so Student s1(10,"ABC",35) and Student s2(10,"XYZ",67) both are same. So when I say students.insert(s1) and students.insert(s2), set will have only one object i.e. s1.
I've never done this in c++ but a quick look at http://www.cplusplus.com/reference/set/set/set/
explains it nicely.
Basically when you instantiate the set you need to give it a comparison object which " returns true if the first argument goes before the second argument"
for ints it could be
struct classcomp {
bool operator() (const int& lhs, const int& rhs) const
{return lhs<rhs;}
};
in your case that would be more like
struct StudentCompare{
bool operator() (const Student& lsh, const Student& rhs) const
{
return lhs.rollNo < rhs.rollNo; //or however they need to be compared
}
};
and then you can instantiate it like
std::set<int,StudentCompare> mySet;
This wont work as is for your code as rollNo is private. I recommend that you read the page i linked to above to better understand is going on.
You need to declare and define friend operator> for class Student
Example code
class Student {
/* everything you already have */
public:
friend bool operator<(const Student& lhs, const Student& rhs);
};
bool operator<(const Student& lhs, const Student& rhs) {
return lhs.rollNo < rhs.rollNo;
}
Solution provided thermite does not work because compare function doesn't have access to private members of class Student. To solve this problem, you can declare operator< as friend. A friend function (or class) can access the private and protected members of the class in which it is declared as a friend.
The way I do this is just define the less then operator - if neither of two elements is less then the other then they are effectively equal/equivalent to each other - the "original" thread linked by Daniel shows this nicely.

c++ less operator overload, which way to use?

For example: in a C++ header file, if I defined a struct Record and I would like to use it for possible sorting so that I want to overload the less operator. Here are three ways I noticed in various code. I roughly noticed that: if I'm going to put Record into a std::set, map, priority_queue, … containers, the version 2 works (probably version 3 as well); if I'm going to save Record into a vector<Record> v and then call make_heap(v.begin(), v.end()) etc.. then only version 1 works.
struct Record
{
char c;
int num;
//version 1
bool operator <(const Record& rhs)
{
return this->num>rhs.num;
}
//version 2
friend bool operator <(const Record& lhs, const Record& rhs) //friend claim has to be here
{
return lhs->num>rhs->num;
}
};
in the same header file for example:
//version 3
inline bool operator <(const Record& lhs, const Record& rhs)
{
return lhs->num>rhs->num;
}
Basically, I would like to throw the questions here to see if someone could come up with some summary what's the differences among these three methods and what are the right places for each version?
They are essentially the same, other than the first being non-const and allowing you to modify itself.
I prefer the second for 2 reasons:
It doesn't have to be a friend.
lhs does not have to be a Record
The best way to define the less operator is:
struct Record{
(...)
const bool operator < ( const Record &r ) const{
return ( num < r.num );
}
};
Welcome to c++20 where we have even more options.
//version 1
bool operator <(const Record& rhs)
{
return this->num>rhs.num;
}
this one is wrong, it should read:
//version 1
bool operator <(const Record& rhs)const
{
return this->num>rhs.num;
}
as you want the left hand side to be const-qualified as well.
//version 2
friend bool operator <(const Record& lhs, const Record& rhs) //friend claim has to be here
{
return lhs->num>rhs->num;
}
this one is symmetric. So suppose you have a struct Bar with an operator Record.
Then
Record rhs;
Bar lhs;
assert( lhs < bar );
the above works with a symmetric case, but not with a member function version.
The friend in class version is an operator that can only be found via Koenig lookup (Argument Dependent Lookup). This makes it very useful for when you want a symmetric operator (or one where the type is on the right, like ostream&<<*this) bound to a specific template class instance.
If it is outside of the class, it has to be template function, and a template function does overloading differently than a non-template function does; non-template functions permit conversion.
template<class T>
struct point {
T x ,y;
point operator-(point const& rhs)const{
return {x-rhs.x,y-rhs.y};
}
friend point operator+(point const& lhs, point const& rhs) {
return {lhs.x+rhs.x, lhs.y+rhs.y};
}
};
template<class T>
point<T> operator*( point<T> const& lhs, point<T> const& rhs ) {
return {lhs.x*rhs.x, lhs.y*rhs.y};
}
here - is asymmetric, so if we have a type that converts to a point<int> on the left, - won't be found.
+ is symmetric and a "Koenig operator", so it is a non-template operator.
* is symmetric, but is a template operator. If you have something that converts-to-point, it won't find the * overload, because deduction will fail.
//version 3
inline bool operator <(const Record& lhs, const Record& rhs)
{
return lhs->num>rhs->num;
}
this is similar to the template above, but here that problem doesn't occur. The difference here is that you can get the address of this function outside of the class, while the "koenig operator<" you wrote can only be found via ADL. Oh, and this isn't a friend.
c++17 adds in
auto operator<=>(const Record&)=default;
where we use the spaceship operator <=> to define ordering automatically.
This will use the ordering of both c and num to produce the required result.
Much like the rule of 5, you should seek to make =default here work correctly. Having state that < ignores is a bad smell, and so is entangling different parts of your state.
The non-member equivalent of your member function
bool operator <(const Record& rhs);
is
bool operator <(Record& lhs, const Record& rhs); // lhs is non-const
Now STL containers treat the items they store as const (at least as long as the comparison operator is concerned). So they call const-const variant of your operator. If they don't find it (in case you provided variant 1 only) - it is a compile error.
If you provide both const-const member and const-const non-member:
struct Record
{
bool operator <(const Record& rhs) const;
};
bool operator <(Record& lhs, const Record& rhs);
it is yet another compiler error because such definition leads to an ambiguity:
If two matches are found at the highest level where a match is found,
the call is rejected as ambiguous. /Stroustrup, C++, section 12.3.1/
Finally, (as noted in the previous answers) there's no need in the friend modifier since by default all fields of the struct are public.
PS make_heap doesn't expect the compared items to be const because it is a more low-level beast and using it you're kind of co-authoring a new heap-based library so it is your responsibility to track const-ness of items.
PPS set treatment of items as const does not protect you from modifying the keys of the items after they are inserted into the container - it will result in a runtime error (segfault) if you try it.
Favor in-class unless it cannot be in-class because first argument is the wrong type.

Invalid conversion error when overloading ostream& operator<<

Here is the prototype of my class Rational
#ifndef RATIONAL_H
#define RATIONAL_H
//forward declaration
class ostream;
class Rational
{
int numerator,denominator;
public:
// the various constructors
Rational();
Rational(int);
Rational(int,int);
//member functions
int get_numerator()const{return numerator;}
int get_denominator()const{return denominator;}
// overloaded operators
// relational operators
bool operator==(const Rational&)const;
bool operator<(const Rational&)const;
bool operator<=(const Rational&)const;
bool operator>(const Rational&)const;
bool operator>=(const Rational&)const;
//arithmetic operators
Rational operator+(const Rational&)const;
Rational operator-(const Rational&)const;
Rational operator*(const Rational&)const;
Rational operator/(const Rational&)const;
//output operator
friend ostream& operator<<(ostream&, const Rational&);
};
#endif //RATIONAL_H
And this is the implementation of the overloaded output operator<< in rational.cpp
// friend output operator
ostream& operator<<(ostream& os, const Rational& r)
{
os<<r.get_numerator()<<"/"<<r.get_denominator();
}
When I try to compile I get the following error
g++ -c rational.cpp
rational.cpp: In function ‘ostream& operator<<(ostream&, const Rational&)’:
rational.cpp:81:26: error: invalid conversion from ‘const char*’ to ‘int’ [-fpermissive]
rational.cpp:7:1: error: initializing argument 1 of ‘Rational::Rational(int)’ [-fpermissive]
I wanted to be able to display the rational number as numerator/denominator when it is passed to the << operator.
Your first issue is that you try to forward declare ostream as a class. Assuming that you mean to use std::ostream, you can't do that, its not legal.
For one, it's a typedef for a template specialization, not a class itself.
Second, because you don't #include <ostream> you don't have a definition for any of the standard << overloads for ostream so when you try to << a string literal, the compiler trys to convert the string literal to a Rational type as that is the only type that has a << overload visible.
Simply, you need to #include <ostream> and qualify ostream with std:: where you use it.
A third point is that your overload of operator<< needs to return something. You should either append a return os; statement or simply return the whole streaming expression.
Although I am not sure why you get such error message, I do found an error: you should add:
return os;
in your friend function.