At work I've been using linux and the GCC compiler for C++11 and C++14. In some of the code at work, I've used a union to store both a reference and a pointer, as so: (Simplified to just the important parts)
struct MyStruct
{
//Stuff
union { double& x; double* x_ptr; };
MyStruct(double& value) : x(value) {}
//More stuff
};
I believe this code is clear, readable, unambiguous, and provides a convenient way to store references which can be shifted to something else. It provides easily understandable syntactic sugar without costing performance while improving readability. When I attempted to use code like this in visual studio 15, however, the code failed to compile due to "an illegal union member of type double&".
Note: At my work, pretty much all code is written for Linux and compiled with GCC, and for my specific project, C++11 is guaranteed and GCC is the only compiler that's going to be used.
Edit: Please don't tell me that putting a reference inside a union "has no meaning". When a reference is stored inside a struct, it takes up the same amount of space as a pointer. In addition, the following compiles with clang:
struct MyStruct
{
//This will compile
union
{
struct { double& x; };
double* x_ptr;
};
//This won't compile; WHY?
/*union
{
double& x;
double* x_ptr;
};*/
MyStruct(double& val) : x(val){}
void Repoint(double& new_value)
{
x_ptr = &new_value;
}
};
Why does it compile when the reference is wrapped in an anonymous struct, but not when it's just in the union?
live example
The primary use of a union is allowing access to a common location by different data types, for example hardware input/output access, bitfield and word sharing, or type punning. Unions can also provide low-level polymorphism.
A union is a user-defined type in which all members share the same memory location. This definition means that at any given time, a union can contain no more than one object from its list of members.
If a union of two types is declared and one value is stored, but the union is accessed with the other type, the results are unreliable. For example, a union of float and int is declared. A float value is stored, but the program later accesses the value as an int .
A union can have member functions (including constructors and destructors), but not virtual functions. A union cannot have base classes and cannot be used as a base class.
In addition to @Brian:
You can make it compile by using e.g. std::reference_wrapper
instead of a plain reference:
#include <functional>
struct MyStruct
{
//Stuff
union { std::reference_wrapper<double> x; double* x_ptr; };
MyStruct(double& value) : x(value) {}
//More stuff
};
int main()
{
double value = 123;
MyStruct myStruct(value);
}
live example
It is illegal for a union to contain a reference member. This is presumably because references are not objects and it's unspecified whether or not they occupy storage---so it makes little sense for a reference to share its storage with other variables.
A union can have member functions (including constructors and destructors), but not virtual (10.3) functions. A union shall not have base classes. A union shall not be used as a base class. If a union contains a non- static data member of reference type the program is ill-formed.
([class.union]/2)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With