On 2005-05-15 00:49:54 +0100, "Peter Dimov" said:
intrusive_ptr<T> is convertible to intrusive_ptr<U> when T*
is convertibl e to U*.
It does, indeed! Many thanks. Not sure why I thought that the
guarantee given by shared_ptr somehow negatively implied that
such a guarantee wouldn't hold for intrusive_ptr. I was wrong.
in http://www.boost.org/libs/smart_ptr/smarttests.htm
there's a mention of a "cyclic" smart pointer implementation
that dealt with cycles "using a dequeue". Is this available
somewhere (I couldn't locate it in boost 1.32) ?
Anyway, here's my revised snippet that satisfies all my criteria:
- polymorphic covariance (for lack of a better name :)
- ad lib creation of the envelope from the base type
without any concern about "lack of sharing"
- and, the icing on the cake: I haven't any qualm any more
about passing intrusive_ptr<T> around by value since they're
only the size of a pointer and thus should entirely fit in
in a register.
Thanks again.
--
JFB
#include <iostream>
#include
struct ObjectStruct {
int refCount ;
ObjectStruct() : refCount(0) {
std::cout << std::hex << (int) this << " - I'm born" <<
std::endl ;
}
void refer() { ++refCount ; }
void unrefer() { if (--refCount == 0) delete this ; }
virtual ~ObjectStruct() {
std::cout << std::hex << (int) this << " - I'm gone" <<
std::endl ;
}
} ;
void intrusive_ptr_add_ref(ObjectStruct * p) { p->refer() ; }
void intrusive_ptr_release(ObjectStruct * p) { p->unrefer() ; }
struct TaskDoneStruct : public virtual ObjectStruct {
virtual void success() = 0 ;
virtual void failure() = 0 ;
} ;
typedef boost::intrusive_ptr<TaskDoneStruct> TaskDone ;
struct MyTaskDone : public TaskDoneStruct {
virtual void success() {
std::cout << "MyTaskDone::Done lengthy process ..." <<
std::endl ;
}
virtual void failure() {
std::cout << "MyTaskDone::Aborted lengthy process ..." <<
std::endl ;
}
} ;
struct LongTaskStruct : public virtual ObjectStruct {
TaskDone callback ;
virtual void setCallback(const TaskDone& td) {
this->callback = td ;
}
virtual void run() {
start() ;
complete() ;
}
virtual void start() = 0 ;
virtual void complete() {
if (callback) {
callback->success() ;
}
}
virtual ~LongTaskStruct() {}
} ;
struct MyTaskStruct : public LongTaskStruct
, TaskDoneStruct {
MyTaskStruct() {
setCallback(TaskDone(this)) ;
}
virtual void start() {
std::cout << "Starting lengthy process ..." << std::endl ;
}
virtual void success() {
std::cout << "Done lengthy process ..." << std::endl ;
}
virtual void failure() {
std::cout << "Aborted lengthy process ..." << std::endl ;
}
} ;
struct MyFailingTaskStruct : public MyTaskStruct {
virtual void start() {
std::cout << "Aborting lengthy process ..." << std::endl ;
if (callback) {
callback->failure() ;
}
}
} ;
typedef boost::intrusive_ptr<MyTaskStruct> MyTask ;
typedef boost::intrusive_ptr<MyFailingTaskStruct> MyFailingTask ;
void callTask(MyTask task) {
task->run() ;
}
void
taskTest2() {
MyTask myTask(new MyTaskStruct) ;
callTask(myTask) ;
MyFailingTask myFailingTask(new MyFailingTaskStruct) ;
callTask(myFailingTask) ;
}
void
taskTest() {
MyTask myTask(new MyTaskStruct) ;
myTask->run() ;
myTask->setCallback(myTask) ;
myTask->run() ;
myTask->setCallback(TaskDone(new MyTaskDone)) ;
myTask->run() ;
}
int
main(
int argc
, char * argv[]) {
std::cout << "Tests starting ..." << std::endl ;
taskTest() ;
taskTest2() ;
std::cout << "Tests done ..." << std::endl ;
return 0 ;
}
/*
Tests starting ...
30018c - I'm born
Starting lengthy process ...
Done lengthy process ...
Starting lengthy process ...
Done lengthy process ...
3001a4 - I'm born
Starting lengthy process ...
MyTaskDone::Done lengthy process ...
3001a4 - I'm gone
30018c - I'm gone
30018c - I'm born
Starting lengthy process ...
Done lengthy process ...
3001bc - I'm born
Aborting lengthy process ...
Aborted lengthy process ...
Done lengthy process ...
Tests done ...
*/
--
Do your users a favor: give them Style: http://www.uiwithstyle.org