2

I am designing a class that behaves like a C++ references but does some extra instrumental stuff (bookkeeping).

Initially I thought that std::reference_wrapper<T> would be a good model. But after a while I realized that std::reference_wrapper<T> doesn't behave, even in principle, as a C++ reference because assignment rebinds the internal pointer.

    double a = 5.;
    double b = 3.;
    double& ref = a;
    ref = b;
    assert(&ref != &b); // ref is not bound to b
    std::reference_wrapper<double> refwpr = a;
    refwpr = b;
    assert(&refwpr.get() == &b); // ref wrapper was rebound to b

I can of course change that behavior for my own class (not to rebind) but I though that maybe a class that emulates a reference is already out there. For example something like "std::real_reference<T>".

Is there a class (standard or not) that emulates references more closely?

I think it can be useful too, for example in many places one sees std::vector<std::reference_wrapper<T>> presented as an alternative to std::vector<T&> but this is misleading because the semantics is different but could be achieved with some modifications std::vector<std::real_reference<T>>.


I now think that if a "perfect" reference wrapper were possible, then references could be just implemented with pointers and we wouldn't need T& but just simply have a library feature reference<T> that works exactly like T& in all respects....

... which in turn means that the language could allow you to "overload" the & attribute over types to produce a custom type instead of a language reference. For example using mytype& = custom_reference_emulator_of_mytype.

alfC
  • 14,261
  • 4
  • 67
  • 118
  • Are there any other issues with `std::reference_wrapper`? If not, why not just implement your own version with everything included but the operator overload for copy assignment? – Joel Cornett Dec 12 '15 at 05:06
  • @JoelCornett Yes, there are other issues, since my reference emulator needs to have the same semantics as a real reference I need to overload `operator&` to return the same as `&a`, that is (something convertible to) a pointer to the original object. But I left that out of the question. (In fact I have to overload a lot of operators to make it behave like a real reference and even `operator.` if that were possible.) http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4173.pdf – alfC Dec 12 '15 at 05:22
  • @JoelCornett, Yes, I can implement my own but there are so many details to take into accout that I wondered if such thing existed already. – alfC Dec 12 '15 at 05:22
  • 1
    Your code shouldn't compile. You're comparing pointer-to-double with double. – tonytony Dec 12 '15 at 06:39
  • Yep, [doesn't compile](https://ideone.com/qiKOU8) either assertion – Eric Dec 12 '15 at 07:21
  • `reference_wrapper` doesn't try to behave as a reference - it simply wraps one. If you want the underlying reference, use `.get()`. – Eric Dec 12 '15 at 07:22
  • @tonytony Now fixed. – alfC Dec 12 '15 at 08:29
  • @Eric. Yes i figured that out. reference_wrapper was not made for that. I wonder if there is something to emulate a reference. (I have strong opinions on reference_wrapper. I think it was a mistake induced by the lack of rvalue references at the time) – alfC Dec 12 '15 at 08:35
  • What is the bookkeeping going to look like here? – Eric Dec 12 '15 at 16:48

1 Answers1

2
template <typename T>
class Tref {
    std::tuple<T &> t;
public:
    template <typename... Args>
    Tref(Args&&... args): t(std::forward<Args>(args)...) {}
    operator T &() { return std::get<0>(t); }
    decltype(&std::get<0>(t)) operator&() { return &std::get<0>(t); }
};


Tref<double &> t(a);
t = b;
assert(&t != &b);

What std::reference_wrapper does is binding when the template erase the reference. You needn't build a class to meet your needs, and just use normal reference. (I may not describe clearly. My English is poor.)

linux40
  • 368
  • 1
  • 9
  • Thanks, Do you find any advantage on using a `std::tuple` instead of `class Tref{T& t;...`. I have a similar implementation but I am undesided between using a pointer (like `std::reference_wrapper` does) or a reference. (a pointer is more flexible.) – alfC Dec 12 '15 at 23:09