Confused why it got solved by using friend function - c++11

I have this question in assignment.
Question:
Implement + and - operators for the Date class where u give dates using constructor and also give and additional n value. Now we have to use operator + and operator - to change the previously taken date by n value.
I have done this and it given an error: operator+(Date&, int) must take either zero or one argument
class Date
{
int day;
int month;
int year;
public:
Date(int d,int m,int y)
{
day=d;
month=m;
year=y;
}
Date operator-(Date &x,int y)
{
return Date(x.day-y, x.month, x.year);
}
Date operator+(Date &x,int y)
{
return Date(x.day+y, x.month, x.year);
}
void display()
{
cout<<"Date:"<<day<<"-"<<month<<"-"<<year<<endl;
}
};
After i searched in web and found this:
class Date{
private:
int day;
int mth;
int year;
public:
Date(int a,int b,int c){
day = a;
mth = b;
year = c;
}
friend Date operator +(Date &,int);
friend Date operator -(Date &,int);
void print(void){
cout <<"Date: " << day << " - " << mth << " - " << year << endl;
}
};
Date operator +(Date& a,int n){
Date d(a.day+n,a.mth,a.year);
return(d);
}
Date operator -(Date& a,int n){
Date d(a.day-n,a.mth,a.year);
return(d);
}
My Doubt: Both are same but he used friend function and it got solved. In both cases the operator overloading function is same and error is also pointing towards the function. How this friend function solved the issue or anything wrong in my Operator overload function?

In the first code snippet, the operator functions are member functions, so they should be operator+(int) instead of operator+(Date&, int), since the first argument of type Date & is implicit.
In the second code snippet, the operator functions aren't member functions, so you need a friend qualifier to access the private members of Date.

Related

feeding a stringstream to a class member function

I am a newbie trying to learn by doing. I want to feed a stringstream into a class member function called "print()" but I get errors. Once this works, I can proceed to write more class member functions that work with the data I feed them.
For now I have created a class that has a member function 'print'.
class Month
{
public:
string m_month;
void print()
{
cout << m_month << endl;
}
};
Next, I initialized 12 months:
Month month1 = { "January" };
Month month2 = { "February" };
Month month3 = { "March" };
etc.
When I call "month1.print();" it prints January which is correct.
I used stringstream and a for loop to concatenate month + 1 to 12 and I want to feed the stringstream to the print function.
stringstream os;
string mValue = "month";
int iValue = 1;
for(int i = 0; i < 12; ++i)
{
os << mValue << "" << iValue << "\n";
iValue += 1;
}
However, the stringstream can't be combined with the print function.
os.print(); and os.str().print();
result in "error: ‘std::stringstream {aka class std::__cxx11::basic_stringstream}’ has no member named ‘print’"
Converting the stringstream to char and then feeding it into the print function results in "error: request for member ‘print’ in ‘cstr’, which is of non-class type ‘const char*’"
const string tmp = os.str();
const char* cstr = tmp.c_str();
cstr.print();
Long story short: What I am trying to do is concatenate month + 1 to 12 and feed that to the class member function "print". This seems trivial but I can't get it to work. Any suggestions?
Edit: Full code:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
class Month
{
public:
string m_month;
void print()
{
cout << m_month << endl;
}
};
int main()
{
Month month1 = { "January" };
Month month2 = { "February" };
Month month3 = { "March" };
Month month4 = { "April" };
Month month5 = { "May" };
Month month6 = { "June" };
Month month7 = { "July" };
Month month8 = { "August" };
Month month9 = { "September" };
Month month10 = { "October" };
Month month11 = { "November" };
Month month12 = { "December" };
stringstream os; // Initialize stringstream "os"
string mValue = "month"; // Initialize mValue "month"
int iValue = 1; // Initialize iValue "1"
for(int i = 0; i < 12; ++i)
{
os << mValue << "" << iValue << "\n"; // Glue mValue and iValue
// together
iValue += 1; // Increment iValue by one
}
send stringstream "os" to the print function // mock code: Here I want to send month1.print(); month2.print(); etc. to the print function. The output should be January, February etc.
return 0;
}
This doesn't do what you think it does:
for(int i = 0; i < 12; ++i)
{
// iValue is actually unnecessary. You could have just used (i + 1)
os << mValue << "" << iValue << "\n";
iValue += 1;
}
All this does is fill the stringstream with the string:
"month1\nmonth2\nmonth3\nmonth4\nmonth5\nmonth6\nmonth7\nmonth8\nmonth9\nmonth10\nmonth11\nmonth12"
Your intent seemed to be to concat a number to the end of a "month" string, and have them act as the month1, month2... variables that you defined above. That's not how it works. You can't (and shouldn't) try to "dynamically" reference variables like that. In os.print();, the stringstream doesn't act as Month simply because it contains a string with the same name as a Month variable.
Instead, add the variables to some kind of container (like a std::vector), and loop over it:
std::vector<Month> months{ month1, month2, month3, ..., month12 }
for (unsigned int i = 0; i < months.size(); i++)
{
months[i].print();
}
A stringstream should be thought of as a stream like any other, except that it happens to be text and held in memory. So it's cheap to convert it to a string, and in fact they are often used for building strings.
But a "Print" method of a class has no business knowing that a stream is a stringstream. All it should care is that it gets a stream which is text, and is input. In fact the former is a bit hard to enforce due to historical weaknesses stretching back a long way. If you just read the stream byte by byte, pass to std::cout, and terminate on EOF then that's probably OK.

MSVC++ 2013 seems to allow assignments to temporary objects, effectively treating them as lvalues

I've come across this "feature" in MSVC++ and I'm now not sure if it's a bug or my understanding of lvalues/rvalues in C++ is just plain wrong.
I've added some seriously dumbed-down code to illustrate, but basically the issue is that MSVC++ 2013 (both base and NOV 2013 CTP compilers) allows assignment to temporary objects, which should really be rvalues and hence disallow any assignment attempts at compile time.
#include <iostream>
struct account {
int value;
explicit account(int v) : value{ v } {
std::cout << "account ctor: " << value << std::endl;
}
account(const account & acc) : value{ acc.value } {
std::cout << "account copy ctor" << std::endl;
}
account(account && acc) : value{ acc.value } {
std::cout << "account move ctor" << std::endl;
}
account & operator=(const account & acc) {
value = acc.value;
std::cout << "account copy assign" << std::endl;
return *this;
}
account & operator=(account && acc) {
value = acc.value;
std::cout << "account move assign" << std::endl;
return *this;
}
};
int get_int() { return 42; }
account get_account() {
return account(123);
}
int main() {
//get_int() = 5; // this predictably fails to compile
// with '=' : left operand must be l-value
// everything below succeeds
get_account() = account(42); // console trace for this
// account ctor: 42
// account ctor: 123
// account move assign
account(123) = account(42); // console trace same as above
account acc(0); // account ctor: 0
account(42) = acc; // account ctor: 42
// account copy assign
get_account() = acc; // console trace same as above
}
Surely get_account() = acc; or account(42) = acc; is not C++ Standard's prescribed behaviour?! Both get_account() & account(42) should result in rvalues, which by definition do not allow assignments.
Incidentally, overloading member functions based on lvalue/rvalue qualifiers
...
void memberFn() const &;
void memberFn() &&;
...
which is supported in NOV 2013 CTP is not working properly or at all. I assume this is a result of failing to recognise rvalues, so that this is always an lvalue.
PS Unfortunately, I do not have an opportunity to test this with other compilers.
According to my understanding, this is perfectly valid C++11.
Only built-in assignment to prvalues is prohibited.
From [5, expr]:
Note: Operators can be overloaded, that is, given meaning when applied to expressions of class type (Clause
9) or enumeration type (7.2). Uses of overloaded operators are transformed into function calls as described
in 13.5. Overloaded operators obey the rules for syntax specified in Clause 5, but the requirements of
operand type, value category, and evaluation order are replaced by the rules for function call.
So the requirements on
get_account() = account(42);
are the same as on any other member-function call
get_account().foo_bar(account(42));
which makes sense since it is just a nicer syntax for
get_account().operator=(account(42));
The section 3.10 on Lvalues and rvalues makes this as clear well [basic.lval]:
For example, the built-in assignment operators expect that the left operand is an lvalue and that the right operand is a prvalue and yield an lvalue as the result. User-defined operators are functions, and the categories of values they expect and yield are determined by their parameter and return
types.

What's wrong with my C++ temperature convertor?

I'm trying to write a program that takes a value in the Fahrenheit scale, validates the value to ensure that it is legitimate, and returns the proper value for Fahrenheit, Celsius, and Newton.
The code below keeps giving error messages for Lines 21, 25, 29 (The void's)
#include <iostream>
using namespace std;
class temperature {
public:
double getFahrenheit();
double getCelsius();
double getNewton();
void setFahrenheit();
void setCelsius();
void setNewton();
private:
double fahrenheit, Celsius;
double c, f;
};
void freezing.setFahrenheit(){
f = 32;
fahrenheit = f;
}
void freezing.setCelsius(){
c = (5.0/9.0) * ( f - 32);
celsius = c;
}
void freezing.setNewton(){
n=(33.0/100.0)*c;
newton=n;
double freezing.getFahrenheit(){
return fahrenheit;
}
double freezing.getCelsius(){
return Celsius;
}
Double freezing.getNewton(){
Return Newton;
}
int main() {
Temperature freezing(32);
Freezing.setFahrenheit(); Freezing.setCelsius();
Freezing.setNewton();
cout << "water freezes at " << freezing.getFahrenheit() << " Fahrenheit, " << freezing.getCelsius() << " Celisus, and " << freezing.getNewton() << " Newton" << endl;
return 0;
}
You need to use :: instead of . Moreover, your class is called temperature and not freezing
void temperature::setFahrenheit()
See also this question
There's a few other errors too:
void temperature::setCelsius(){ //and not void freezing.setCelsius
c = (5.0/9.0) * ( f - 32);
celsius = c;
}
Here you reference celsius , but the temperature class defines Celsius with a captial C.
void freezing.setNewton(){
n=(33.0/100.0)*c;
newton=n;
Here you use the n and newton variables, but you have not defined them anywhere. They should perhaps be members of your temperature class.
Double freezing.getNewton(){
Return Newton;
}
Here you have capital letters, which doesn't make sense, it should be
double temperature::getNewton(){
return newton; //you need to make this a member variable of your class too..
}
Temperature freezing(32);
Your temperature class has a lowercase t , the Temperature class doesn't exist.
And there's no constructor defined, so you can't pass 32 in there.
Freezing.setFahrenheit();
Freezing.setCelsius();
These 2 lines references Freezing, but you called your variable freezing

Get an unsigned int milliseconds out of chrono::duration

For a winapi wrapper I want to use chrono for a duration given to the call. The code example:
bool setTimer(std::chrono::duration<std::chrono::milliseconds> duration)
{
unsigned int dwDuration = Do some chrono magic here
SetTimer(m_hWnd,1,dwDuration,0);
}
dwDuration has to be in milliseconds.
First question: How do to the magic.
Second question: Is the parameter declaration okay?
The name of the type is std::chrono::milliseconds, and it has a member function count() that returns the number of those milliseconds:
bool setTimer(std::chrono::milliseconds duration)
{
unsigned int dwDuration = duration.count();
return std::cout << "dwDuration = " << dwDuration << '\n';
}
online demo: http://coliru.stacked-crooked.com/a/03f29d41e9bd260c
If you want to be ultra-pedantic, the return type of count() is std::chrono::milliseconds::rep
If you want to deal with fractional milliseconds, then the type would be std::chrono::duration<double, std::milli> (and the return type of count() is then double)
You can use the following code:
auto now = chrono::high_resolution_clock::now();
auto timeMillis = chrono::duration_cast<chrono::milliseconds>(now.time_since_epoch()).count();

C++ STL priority_queue with struct Clearification

I have looked over this thread which talks about using this method for comparison:
struct thing
{
int a;
char b;
bool operator<(const thing &o) const
{
return a < o.a;
}
};
priority_queue<thing> pq;
On the other hand other uses method such as this:
struct Time {
int h;
int m;
int s;
};
class CompareTime {
public:
bool operator()(Time& t1, Time& t2) // Returns true if t1 is earlier than t2
{
if (t1.h < t2.h) return true;
if (t1.h == t2.h && t1.m < t2.m) return true;
if (t1.h == t2.h && t1.m == t2.m && t1.s < t2.s) return true;
return false;
}
}
priority_queue<Time, vector<Time>, CompareTime> pq;
While I logic myself with the first method, I don't quit understand the second method. Mostly because of the syntax. I am not quit sure what the overloading operator operator() means. What is that operator overloading?
Also, from cplusplus on priority_queue, I don't quite understand the following, mainly the second parameter.
template < class T, class Container = vector<T>,
class Compare = less<typename Container::value_type> > class priority_queue;
In another word, I don't understand the second method and its calling convention.
Also, what's the difference and which method is preferred?
I am not quit sure what the overloading operator operator() means.
What is that operator overloading?
What we have here is an overloading of the function call operator (see SO question) , this means that client code can 'treat' the CompareTime class instances as compare functions :
CompareTime ct;
if ( ct(t1, t2) )
{
...
}
I don't quite understand the following, mainly the second parameter.
The cplusplus reference summarizes quite well , the template parameters :
0 arg - The type of the objects within the queue.
1 arg - The underlying container/data structure for the queue, by
default its the std vector
2 arg - Operation on priority queue relies on some precedence
comparison, i.e. which item in the queue should be 'before' other item (see also Wikipedia , so this arg accepts to have compare object (functor) which mean instances of plain class which overload the () operator , the default is the std less functor which is simply a wrapper above the '<' semantics (boolean 2 valued function object).
// TEMPLATE STRUCT less
template<class _Ty>
struct less : public binary_function<_Ty, _Ty, bool>
{
// functor for operator<
bool operator()(const _Ty& _Left, const _Ty& _Right) const
{
// apply operator< to operands
return (_Left < _Right);
}
};

Resources