|
Boost : |
From: Powell, Gary (powellg_at_[hidden])
Date: 2004-02-11 18:18:22
--------------------------------
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-
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk