Edit: Welp, I guess this was a terrible idea.
Is it possible to make a smart reference in C++ (for a specific class, since you can't overload the . operator) with the same semantics as a normal C++ reference, but which is reseated when used in an STL container?
For example, if I have some int_ref class with the normal integer operators overloaded, and construction and assignment looks like this:
class int_ref{
int * p;
public:
int_ref(int * ip) : p(ip) {}
int_ref(const int_ref & other) : p(other.p) {
/* maybe some refcounting stuff here */
}
int_ref & operator = (const int_ref & other){
if (!p)
throw something_bad();
*p = *other.p;
return *this;
}
void reseat(const int_ref & other){
p = other.p;
}
}
Then I can't use this with std::vector since it won't reseat the references, and I don't want this kind of thing:
std::vector<int_ref> vec;
int_ref five = new int(5);
vec.push_back(five);
vec.push_back(new int(1));
std::sort(vec.begin(), vec.end()); // the value of five is now 1
I can use rvalue references to make it play nice with the STL,
int_ref & operator=(int_ref && other){
reseat(other);
return *this;
}
But then a function that returns an int_ref would use the rvalue overload, and I'd get this:
int_ref make_number(){
return new int(10);
}
int_ref ref = new int(5);
int_ref other = ref;
other = make_number(); // instead of copying, as a reference would,
// other now points to something other than ref
Is there a way around this? Is this just a terrible idea in general?
One problem with even trying to do this is operator&. For a reference, it gives you the address of the referand (since references have no address). For a element of a container, though, it's expected to give you the address of the element (since those do have addresses).
So, an element of a container cannot mimic reference semantics in this respect. If you overload operator& to return the address of the referand, then for example the contiguous storage guarantee of vector is violated, since it says &v[n] == &v[0] + n for all 0 <= n < v.size()
boost::addressof() was invented to work around this problem, so that you don't have to use & to get the address of an object in generic code. But even the standard is too lazy to say static_cast<T*>(&static_cast<char&>(v[n])) rather than &v[n]. Even when you're thinking of using it, it's quite difficult to decide when you want the actual address of the object, and when you want the address that the author of the object thinks you want. It's best just never to overload unary operator&. That means you'll get a partial version of reference semantics, which potentially is confusing in its own way.
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