I decided that my serial_ptr implemented a variant at the wrong level of indirection. So now I'm trying out intrusive_ptr with a variant at the pointee level. This is what my code looks like now:
//----------------------------------------------------------------------- class TRecord { public: // Interface TRecord(void) : ID_(0) { } TRecord(int ID) : ID_(ID) { } virtual ~TRecord(void) { } void swap(TRecord& Record) { std::swap(ID_, Record.ID_); } int ID(void) const { return ID_; } private: // Implementation int ID_; }; //----------------------------------------------------------------------- template <typename T> class TCountedRecord { public: // Interface TCountedRecord(void) : Count_(0) { } TCountedRecord(int ID) : Count_(0) { new (Value_) TRecord(ID); } ~TCountedRecord(void); bool IsRecord(void) const; // No-throw unsigned Count(void) const; // No-throw int ID(void) const; operator T const&(void) const; operator T&(void); T* AddRef(void); void Release(void); // No-throw private: // Implementation typedef boost::detail::lightweight_mutex mutex_type; mutable mutex_type Mutex_; unsigned Count_; char Value_[sizeof(T)]; }; //----------------------------------------------------------------------- template <typename T> void intrusive_ptr_add_ref(TCountedRecord<T>* p) { p->AddRef(); } //----------------------------------------------------------------------- template <typename T> void intrusive_ptr_release(TCountedRecord<T>* p) { p->Release(); } This code is still being designed, so I haven't tried it. It might not work as expected. The idea is that my database records will derive from TRecord, and my pointers will be intrusive_ptrs to TCountedRecord<T>. In case it's not obvious, TCountedRecord is a variant of TRecord and T. The idea is when I just get record IDs, a TCountedRecord stores a TRecord with the ID in it. When I get a full record, I use placement new to install it over the TRecord. I have several issues, however. First, the variant doesn't support inheritance hierarchies very well. If I have U derived from T, my problem is that TCountedRecord<U> isn't derived from TCountedRecord<T>, and so I can't use dynamic_pointer_cast<> to cast between my intrusive_ptrs. That's not a problem with dynamic_pointer_cast<>, of course. The problem is that I can't store base pointers at all, since the pointers aren't related. Second, I don't like having to use placement new to construct my records, but I can't use inheritance, because I don't always have all the data to construct a full record immediately. So the variant essentially implements "partial construction". If I could just have T, rather than variant<TRecord, T>, and only construct the TRecord sub-object, that would be ideal, but obviously, not C++. Another solution is to use a pointer in TCountedRecord instead of a value. However, that introduces an unnecessary level of indirection (though I might be forced to resort to that). Another thing that's not obvious from the interface is that I'm using the count as the variant tag. A 0 means that a TRecord is present, and a non-0 means an actual record is present. Any suggestions on how to deal with polymorphism, or restructure the design differently are appreciated. Also, I think Boost could use a value-based variant type. Dave _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost