Reputation: 53129
I'm creating a function to get a const int
time in seconds and print real time in hours minutes and seconds.
localtime
can do that, returning tm
structure from time.h
. What I panned to do was this:
bool elapsed(const int timeout) {
//Cast the integer to time_t
struct tm * now = localtime( (time_t&) &timeout);
std::wcout<<L"Time elapsed: "<<now->tm_hour<<':'<<now->tm_min<<':'<<now->tm_sec<<"\r\n";
return timeout>600;
}
But this throws an error: (time_t&)
&
timeout
- expression must be an lvalue
Besides troubling me with an
before a consonant, the error makes no sense to me. I've read that lvalues are things with names. Is this case an exception?
Upvotes: 1
Views: 2823
Reputation: 263237
The localtime
function requires an argument of type time_t*
, a pointer to a time_t
object.
In your current code, you don't have a time_t
object, so you can't create a valid pointer to such an object.
Define a local time_t
object, initialized to the (converted) value of timeout
, and pass that object's address to localtime
:
bool elapsed(const int timeout) {
time_t t_timeout = timeout;
struct tm * now = localtime(&t_timeout);
// ...
But if possible, it would be cleaner to declare your timeout
parameter as a time_t
in the first place:
bool elapsed(time_t timeout) {
struct tm * now = localtime(&timeout);
// ...
This all assumes that your timeout
value is a sensible value to pass to localtime()
. It very likely isn't. A time_t
value represents a time, not a duration; on many systems, it's the number of seconds since 1970-01-01 00:00:00 GMT. A timeout
value of 3600, for example, would represent 1:00 AM on Jan 1, 1970. localtime
as the name implies, treats it as a local time, so depending on your time zone it might be, for example, 4pm on December 31. And that's all assuming the most common interpretation of time_t
values; the language standard only guarantees that it's an arithmetic type able to represent times somehow.
If your goal is to break down your timeout
value into hours, minutes, and seconds, just do the arithmetic yourself:
int seconds = timeout % 60;
int minutes = timeout / 60; // integer division truncates
int hours = minutes / 60;
minutes %= 60;
As for why you got that particular error message: a reference has to refer to an object. When I compile your code with g++ I get:
c.cpp:6:45: error: invalid cast of an rvalue expression of type
'const int*' to type 'time_t& {aka long int&}'
An lvalue is, roughly, an expression that refers to an object. Given
int x = 42;
the expression x
is an value, but 42
and x+1
are not.
The expression timeout
is an lvalue, because it's the name of an object. The expression &timeout
is not an lvalue. It evaluates to a value (the address of timeout
, of type time_t*
), but does not refer to an object, because you don't have an an object of type time_t*
for it to refer to.
You can convert (cast) an lvalue to a reference type. Since &timeout
is not an lvalue, the cast is invalid.
But that doesn't really matter, because converting to a reference doesn't make sense in this context. Telling you how to do the cast correctly would not be helpful, since no cast is required or appropriate for what you're trying to accomplish. All you need is a little simple arithmetic -- no pointers, no references, no casts.
Upvotes: 4
Reputation: 320421
Lvalues are indeed "things with names" (typically, even though this is not an exact rule). But in your case the "thing" in question is &timeout
. This expression evaluates to the address of timeout
variable. This address does not have a name. The address is just a temporary intermediate value. It is obviously not an lvalue.
The reason the compiler requests an lvalue is your cast to reference type (time_t &)
. Only lvalues can be used as operands of such cast. This must be a typo on your part, since localtime
expects a pointer to time_t
as an argument, not a reference. Your cast was apparently supposed to look as (time_t *)
(or, better, (const time_t *)
), but you mistyped &
in place of a *
.
Of course, the very practice of reinterpreting an int
lvalue as an time_t
lvalue (which is what you do with your &
-and-cast combination) is rather questionable. If you know that your time_t
is an integer type and want to rely on that, then conversion would make more sense than reinterpretation
time_t tt_timeout = timeout;
struct tm * now = localtime(&tt_timeout);
Upvotes: 1
Reputation: 170065
Replace (time_t&)
with (time_t*)
.
That will solve the build error. Most likely leading to a runtime error.
Upvotes: 0