Reputation: 2533
Is it possible in C++ to create a union that would let me do something like this ...
union myTime {
long millis;
double seconds;
};
BUT, have it somehow do the conversion so that if I input times in milliseconds, and then call seconds, it will take the number and divide it by 1000, or conversely, if I input the number in seconds, then call millis, it would multiply the number by 1000...
So that:
myTime.millis = 1340;
double s = myTime.seconds;
Where s would equal 1.34
or
myTime.seconds = 2.5;
long m = myTime.millis;
Where m would = 2500
Is this possible?
Upvotes: 1
Views: 176
Reputation: 126418
You can if you abuse the type system a bit:
union myTime {
double seconds;
class milli_t {
double seconds;
public:
milli_t &operator=(double ms) {
seconds = ms/1000.0;
return *this; }
operator double() const { return seconds * 1000; }
} millis;
};
Now if you do
myTime t;
t.millis = 1340;
double s = t.seconds;
s would equal 1.34
and
myTime t;
t.seconds = 2.5;
long m = t.millis;
m would be 2500, exactly as you desire.
Of course, why you would want to do this is unclear.
Upvotes: 1
Reputation: 11230
To answer the question as asked: No. Unions are lower-level structure that simply allow multiple object representations to live in the same memory space. In your example, long
and double
share the same address.
They are not, however, smart enough to automatically do a conversation of any kind. Accessing the inactive member of a union
is actually undefined behavior in most cases (there are exceptions for if you have a common-initial sequence in a standard-layout object).
Even if the behavior were well-defined, the value you would see in the double
would be the double
interpretation of the byte-pattern necessary to represent 1340
.
If your problem is specifically to do with converting millis
to seconds
, as per your example, have you considered using std::chrono::duration
units? These units are designed specifically for automatically doing these conversions between time units for you -- and you are capable of defining durations with custom representations (such as double
).
Your example in your problem could be rewritten:
using double_seconds = std::chrono::duration<double>;
const auto millis = std::chrono::millis{1340};
const auto m = double_seconds{millis};
// m contains 1.340
Upvotes: 1
Reputation: 822
A union
is just different representations for the same value (the same bytes), so you can't define any smart logic over that.
In this case, you can define a class
with conversion functions (both for initializtion or for getting the data).
class myTime {
public:
myTime(long millis);
double as_seconds();
static void from_seconds(double seconds);
};
Notice that as mentioned in other answers, for time conversions you can use std::chrono
objects (c++11 and above)
Upvotes: 3