0

This is a follow up to my previous question on references within classes (Is there an elegant way to swap references in C++?). That approach received some criticism for improper use of union and its code being not portable. This time I modified the approach in order to make the code more portable. Instead of swapping references I will now illustrate assignment of references, for the sake of simplicity. The central idea is to use placement new operator for re-assigning a reference:

struct A
{
   int& r_;
public:
   A(int& v) : r_(v) {}
   int& get() { return r_; }
   void operator=(const A& a)
   {
      new(this)A(a.r_);
   }
};

If a class need to contain more than just references as member variables, then all the references can be grouped in a base class with the corresponding assignment operator. The full example can be found here: https://ideone.com/bGcdxP. What do you think of this approach? Does it have any drawbacks that would prevent it from being used in production code?

Community
  • 1
  • 1
bkxp
  • 1,115
  • 1
  • 12
  • 20
  • 3
    ... and you have UB, see [basic.life]/7. References *may* not be reseated (portably). End of story. – dyp Sep 12 '14 at 16:03
  • 2
    I'll just cite Angew here: "The best answer to your problem is: don't use reference members if you need an assignable/swappable class. Just use a pointer member instead." – Pixelchemist Sep 12 '14 at 16:03
  • 2
    If you want something that acts like a pointer, then why not just use a pointer? – Mike Seymour Sep 12 '14 at 16:03
  • @dyp: what is an UB? – bkxp Sep 12 '14 at 16:04
  • Personally, I would never want to use anything like this in production code. – Christian Hackl Sep 12 '14 at 16:04
  • UB = Undefined Behaviour. That is, you have no guarantees from the C++ Standard what this (or your program) is doing if this ever gets executed. – dyp Sep 12 '14 at 16:04
  • @dyp: The constructor code should produce the same results in both cases regardless of using new or placement new. – bkxp Sep 12 '14 at 16:07
  • @Mike Seymour: Reference is assumed to be trivially-constructible. That's why I suggest to combine all references in a separate base class that will produce no side-effects with placement new. – bkxp Sep 12 '14 at 16:08
  • @MikeSeymour It's not well-behaved since there's a reference data member, I added a citation to my first comment. – dyp Sep 12 '14 at 16:10
  • Probably a duplicate of: http://stackoverflow.com/q/21101774 – dyp Sep 12 '14 at 16:12
  • 1
    @dyp: You're right, it is UB. Reuse of storage is only allowed if "the type of the original object is not const-qualified, and, if a class type, **does not contain any non-static data member whose type is** const-qualified or **a reference type**" – Mike Seymour Sep 12 '14 at 16:13
  • Have you considered using [`std::reference_wrapper`](http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper)? – R Sahu Sep 12 '14 at 16:15
  • @R Sahu: For practical purposes, yes, it's possible. However, std::reference_wrapper does not allow the use of dot access operator, or so I was told. – bkxp Sep 12 '14 at 16:20

0 Answers0