They should be called decorators, not bundles. Here is a cleaned version.
class XYZDecorator { static FloatKey kx_, ky_, kz_; public: XYZDecorator(Particle*p): p_(p){}
bool get_is_initialized() { return p_->has_attribute(kx_) && p_->has_attribute(ky_) && p_- >has_attribute(kz_); }
static XYZDecorator::Pointer initialize(Float x=nan, Float y=nan, Float z=nan) { IMP_assert(!is_instance(p_)); p_->add_attribute(kx_, x); p_->add_attribute(ky_, y); p_->add_attribute(kz_, z); }
Float get_x() const { return p_->get_attribute(kx_); }
void set_x(Float x) const { return p_->set_attribute(kx_, x); } // etc };
the user calls XYZDecorator xyz(p); then p.initialize(1,2,3); if needed p.get_x(); etc.
Daniel Russel wrote: > To elaborate further on my proposal from last night, a particle > bundle would look like the following (incorporating some unrelated > proposed changes) > > class XYZBundle { > static FloatKey kx_, ky_, kz_; > public: > XYZBundle(Particle*p): p_(p){} > static bool is_instance(Particle *p) { > return p->has_attribute(kx_) && p->has_attribute(ky_) && p- > >has_attribute(kz_); > } > typedef std::auto_ptr<XYZBundle> Pointer; > > Pointer cast(Pointer *p) { > if (!is_instance(p)) return Pointer(); > else return Pointer(new XYZBundle(p)); > } > > // either > static XYZBundle::Pointer initialize(Particle *p) { > p->add_attribute(kx_, 0); > p->add_attribute(ky_, 0); > p->add_attribute(kz_, 0); > return Pointer(new XYZBundle(p)); > } > // or > static XYZBundle::Pointer initialize(Particle *p, Float x, Float y, > Float z) { > p->add_attribute(kx_, x); > p->add_attribute(ky_, y); > p->add_attribute(kz_, z); > return Pointer(new XYZBundle(p)); > } > Float get_x() const { > return p->get_attribute(kx_); > } > void set_x(Float x) const { > return p->set_attribute(kx_, x); > } > // etc > }; > > The user class > XYZBundle::Pointer xyzp= XYZBundle::initialize(p) to add the right > fields > or > XYZBundle::Pointer xyzp= XYZBundle::cast(p) to use. > > I am a bit uncomfortable about the faking aspect of the design > especially without working reference counting. Since Bundles don't > need to get passed back and forth from python, we could make the > reference counting work. It might be better to just allocate Bundles > on the stack. This removes a memory management issue at the cost of > eliminating the possibility of using a NULL pointer to signify > failure. So things would have to look more like > > class XYZBundle { > static FloatKey kx_, ky_, kz_; > public: > XYZBundle(Particle*p): p_(p){if (!is_instance(p)) p_=NULL;} > > bool get_is_valid() const {return p_ != NULL;} > > static bool is_instance(Particle *p) { > return p->has_attribute(kx_) && p->has_attribute(ky_) && p- > >has_attribute(kz_); > } > > // either > static XYZBundle initialize(Particle *p) { > IMP_assert(!is_instance(p)); > p->add_attribute(kx_, 0); > p->add_attribute(ky_, 0); > p->add_attribute(kz_, 0); > return XYZBundle(p); > } > // or > static XYZBundle::Pointer initialize(Particle *p, Float x, Float y, > Float z) { > IMP_assert(!is_instance(p)); > p->add_attribute(kx_, x); > p->add_attribute(ky_, y); > p->add_attribute(kz_, z); > return XYZBundle(p); > } > Float get_x() const { > return p->get_attribute(kx_); > } > void set_x(Float x) const { > return p->set_attribute(kx_, x); > } > // etc > }; > > the the user calls > XYZBundle xyzb(p); and xyzb.is_valid() to manipulate a Particle > and > XYZBundle xyzb= XYZBundle::initialize(p); to initialize. > > > > _______________________________________________ > IMP-dev mailing list > IMP-dev@salilab.org > https://salilab.org/mailman/listinfo/imp-dev >