Mar 19, 2018

[C++] Union/StandardLayoutType can not have reference data member.

http://en.cppreference.com/w/cpp/concept/StandardLayoutType

Requirements
  • All non-static data members have the same access control 
  • Has no virtual functions or virtual base classes 
  • Has no non-static data members of reference type
  • All non-static data members and base classes are themselves standard layout types

  • A union cannot have data members of reference types.


Why?
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.

About union's data member:
  • If a union contains a non-static data member with a non-trivial special member function (copy/moveconstructor, copy/move assignment, or destructor), that function is deleted by default in the union and needs to be defined explicitly by the programmer.
  • If a union contains a non-static data member with a non-trivial default constructor, the default constructor of the union is deleted by default unless a variant member of the union has a default member initializer .
  • At most one variant member can have a default member initializer.

Code from cppref:
#include <iostream>
#include <string>
#include <vector>
 
union S
{
    std::string str;
    std::vector<int> vec;
    ~S() {} // needs to know which member is active, only possible in union-like class 
};          // the whole union occupies max(sizeof(string), sizeof(vector<int>))
 
int main()
{
    S s = {"Hello, world"};
    // at this point, reading from s.vec is undefined behavior
    std::cout << "s.str = " << s.str << '\n';
    s.str.~basic_string<char>();
    new (&s.vec) std::vector<int>;
    // now, s.vec is the active member of the union
    s.vec.push_back(10);
    std::cout << s.vec.size() << '\n';
    s.vec.~vector<int>();
}

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.