this is really about a bad idea of swapping two references. The references are not supposed to be resetable so it is not supposed to be possible. That much i know.
What i want to do, is to swap two references, in a way one would swap two pointers: the addresses are swapped but not the data. Assume:
int a = 0, b = 1;
int *pA = &a, *pB = &b;
std::swap(pA, pB);
Now *pA is 1 and *pB is 0, but a is still 0 and b is still 1. This is, however, impossible with references:
int a = 0, b = 1;
int &rA = a, &rB = b;
std::swap(pA, pB);
Now the references are swapped, but the original values are swapped as well. The only thing i can think of is this:
template <class _Ty>
struct resetable_ref {
_Ty &ref;
inline resetable_ref(resetable_ref &r)
:ref(r.ref)
{}
inline resetable_ref(_Ty &_ref)
:ref(_ref)
{}
inline resetable_ref &operator =(resetable_ref &r)
{
if(sizeof(resetable_ref) == sizeof(void*)) // compile-time constant (true)
*reinterpret_cast<void**>(this) = *reinterpret_cast<void**>(&r);
else
memcpy(this, &r, sizeof(resetable_ref)); // optimized away as dead code
return *this;
}
inline operator _Ty &()
{
return ref;
}
};
int a = 0, b = 1;
resetable_ref<int> rrA(a), rrB(b);
std::swap(rrA, rrB);
Now a is still 0 and b is still 1, and the references inside rrA and rrB are swapped. Pity that it doesn't work without the rather ugly operator =(). At least it works for me in MSVC, not sure if g++ will accept it (but i imagine it should).
The whole reference swap is supposed to be used in an object which is constructed with a reference to another object inside, and i'd like to make a swap() function on them. I'd like to avoid using pointers because of the nice non-nullarity feature of the references. It would also be a nicer design (except for the resetable_ref itself).
Does anyone has a better idea of how to go about it? Can anyone think of some compatibility / undefined behavior issues one could run into with this?
I wrote most of the code without compiling, please bear with me if you notice some typo.
EDIT: It seems to me that a lot of people is missing the point of the question. I know how to use pointers, or even how to wrap pointers in a nice template. The question is tagged "hack" and that is what is expected. Don't tell me stuff like "don't do it, use pointer" since that is not what i asked. If you don't like the topic, don't answer, but don't downvote the question just because you would use pointer.
A mutable reference is ... no more tha a pointer, for which you need implicit dereferencing like reference have.
template<class T>
class mutable_ref
{
public:
mutable_ref(T& t) :p(&t)
{}
operator T&() { return *p; }
operator const T&() const { return *p; }
void swap(mutable_ref& s)
{ std::swap(p,s.p); }
private:
T* p;
};
// just in case you also want to specialize std::swap for mutable_ref.
// not necessary, since the generic std::swap<T> use twice =, that is available.
namespace std
{
template<class T>
void swap(mutable_ref<T>& a, mutable_ref<T>& b)
{ a.swap(b); }
}
Note the absence of a default ctor, with an initializing ctor taking a reference, that makes this class not-nullable.
The only problem is that, to access eventual T members, being the "." operator, not overridable, you need something elese for that purpose.
The simple thing is use * and -> as...
T* operator->() const { return p; }
T& operator*() const { return *p; }
to be defined inside mutable_ref
declaration-
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