0

When I studied const reference type in C++, I learned returning reference type make use local variable in main function, so I tested how returned normal struct type work in lvalue. so I expected this source won't compile, but it compiled well... :( so I have two question

"Is returned struct variable?, why this code compiled well?"

"if returned struct is not variable, why this code compiled?, I assumed that returned value is rvalue.."

#include<iostream>
#include<cstring>
using namespace std;
struct travel_time
{
    int hour;
    int min;
};
travel_time sumTime(travel_time, travel_time);
int main(void)
{
    travel_time p1, p2,sum;
    cin >> p1.hour >> p1.min;
    cin >> p2.hour >> p2.min;
    sum=sumTime(p1, p2);
    cout << sum.hour << "hour " << sum.min<<"min";
    sumTime(p1, p2) = p1;   //********** why it works? **********
    return 0;
}
travel_time sumTime(travel_time t1, travel_time t2) 
{
    travel_time sum;
    sum.hour = t1.hour + t2.hour+(t1.min+t2.min)/60;
    sum.min = (t1.min + t2.min) % 60;

    return sum;
}
HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
PangDae
  • 13
  • 4
  • Why returend struct can use in lavalue ? :( – PangDae Feb 21 '21 at 08:12
  • Even that is not reference type – PangDae Feb 21 '21 at 08:13
  • What do you mean by "variable"? in your question "Is returned struct variable?" – Hanjoung Lee Feb 21 '21 at 08:24
  • returned value(struct type) used in lvalue, so i thought that is variable – PangDae Feb 21 '21 at 08:27
  • 2
    Does this answer your question? [Function returning struct as LValue](https://stackoverflow.com/questions/37544600/function-returning-struct-as-lvalue) – dxiv Feb 21 '21 at 08:31
  • https://godbolt.org/z/bqqM1T When we compile it as C, it is invalid just like you said. But if you compile it as C++(remove the compiler option `-x c`), it is valid. And I guess the above link by @dxiv would explain why. – Hanjoung Lee Feb 21 '21 at 08:33
  • 1
    @HanjoungLee Right, and `sumTime(t1, t2).hour = 0;` will fail to compile in C++ as well. The struct assignment compiles because it translates to `sumTime(p1, p2).operator=(p1);`. – dxiv Feb 21 '21 at 08:36
  • @HanjoungLee 감사합니다 ㅜㅜㅜㅜㅜ – PangDae Feb 21 '21 at 08:39
  • @dxiv I didn't know difference between c and c++ thanks! – PangDae Feb 21 '21 at 08:39
  • The implicit assignment operator has signature `travel_time& operator=(const travel_time& other);` so it can be called on rvalues, even if it's rather counter-intuitive IMO. You could restrict it to lvalues only using `travel_time& operator=(const travel_time& other) & = default;` . There, the last `&` states that this method can be called only on lvalues, and `=default` implements it by assigning field-by-field. – chi Feb 21 '21 at 10:59

1 Answers1

1

Is returned struct variable?, why this code compiled well?

This doesn't make much sense.

travel_time sum; is a variable. When you call sumTime, you return a copy of this variable, and that copy itself isn't a variable. So the answer is no, the result of calling the function isn't a variable.

I have a feeling what you really wanted to ask is if the result of calling the function is an lvalue - it's not, the result is an rvalue (more specifically, prvalue).

if returned struct is not variable, why this code compiled?, I assumed that returned value is rvalue..

This again makes no sense, unless I replace "variable" with "lvalue".

In C++, you can assign to rvalues of class types (but not of privitive types such as int). Note that struct travel_time is a class, despite using the word "struct". Strictly speaking, there are no structures in C++, only classes.

There are ways to prevent this kind of assignment for your class, but you didn't do that.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
  • Thank you for your clear answer! I think that i should study more about rvalue in c++, especially focus on difference between c and c++! – PangDae Feb 21 '21 at 08:49