--------------------------------
If Rani is right about the reference binding I'd like to find some way
to library-ize this idiom, so your "ref" converting constructor will
come in handy. BTW, you don't need the other "ref" constructor
anymore.
--
Dave Abrahams
----------------------------------------------------------------------
Ok, reusing Andrei's mojo name I've got the following working:
template <class T>
class mojo
{
protected:
struct ref
{
template<class T2>
ref(T2 *rhs) : p(rhs) {} // works if there is a conversion.
template<class T2>
ref(mojo<T2> *rhs) : p( static_cast<T *>(rhs) ) {} // works if there is a conversion.
template<class T2>
ref(mojo<T2> &rhs) : p( static_cast<T *>(rhs.p) ) {} // works if there is a conversion.
T * p;
T *operator->() const
{
return p;
}
T *operator&() const
{
return p;
}
};
mojo() {} // intended to be derived from.
public: // Move stuff
operator ref() {
return ref(this);
}
};
struct X : public mojo<X>
{
....
// non-const rvalue
X(mojo<X>::ref rhs)
: id(++cnt)
, owner(rhs->owner)
{
std::cout << "MOVE X#" << id << " <== X#" << rhs->id << " owner = " << std::boolalpha << rhs->owner << std::endl;
rhs->owner = false;
assert(owner);
}
....
};
struct Y : public X, public mojo<Y>
{
....
// non-const rvalue
Y(mojo<Y>::ref rhs)
: X ( &rhs )
, id(++cnt)
, owner(rhs->owner)
{
std::cout << "MOVE Y#" << id << " <== Y#" << rhs->id << " owner = " << std::boolalpha << std::boolalpha << rhs->owner << std::endl;
rhs->owner = false;
assert(owner);
}
...
};
struct V : virtual public X, public mojo<V>
{
....
// non-const rvalue
V(mojo<V>::ref rhs)
: X( &rhs)
, id(++cnt)
, owner(rhs->owner)
{
std::cout << "MOVE V#" << id << " <== V#" << rhs->id << " owner = " << std::boolalpha << rhs->owner << std::endl;
rhs->owner = false;
assert(owner);
}
...
};
same for class W. (virtual inheritence)
struct U : virtual public V, virtual public W, public mojo<U>
{
....
// non-const rvalue
U(mojo<U>::ref rhs)
: X( &rhs )
, V( &rhs )
, W( &rhs )
, id(++cnt)
, owner(rhs->owner)
{
std::cout << "MOVE U#" << id << " <== U#" << rhs->id << " owner = " << std::boolalpha << rhs->owner << std::endl;
rhs->owner = false;
assert(owner);
}
...
};
And it all seems to work correctly.
IMO it's not too bad of a "library" module. In any case I like using the operator->() as you can stop referencing the pointer "ref.p". And I chose operator &() but perhaps a "get() member fn of mojo is the right thing to do. As to whether to call it mojo or not...well I didn't have another class name in mind.
If you don't have mulitiple inheritence you don't have to specify mojo<Type>::ref, so that's nice as well.
Anyway I saw Bjarne's call for items on the list, and IMO, this topic deserves it if nothing more than to clarify that its OK.
-Gary-