diff --git a/gtsam/base/GenericValue.h b/gtsam/base/GenericValue.h new file mode 100644 index 000000000..78155d308 --- /dev/null +++ b/gtsam/base/GenericValue.h @@ -0,0 +1,143 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/* + * @file DerivedValue.h + * @date Jan 26, 2012 + * @author Duy Nguyen Ta + */ + +#pragma once + +#include +#include + +////////////////// +// The following includes windows.h in some MSVC versions, so we undef min, max, and ERROR +#include + +#ifdef min +#undef min +#endif + +#ifdef max +#undef max +#endif + +#ifdef ERROR +#undef ERROR +#endif +////////////////// + + +namespace gtsam { + +template +class DerivedValue : public Value { + +protected: + DerivedValue() {} + +public: + + virtual ~DerivedValue() {} + + /** + * Create a duplicate object returned as a pointer to the generic Value interface. + * For the sake of performance, this function use singleton pool allocator instead of the normal heap allocator. + * The result must be deleted with Value::deallocate_, not with the 'delete' operator. + */ + virtual Value* clone_() const { + void *place = boost::singleton_pool::malloc(); + DERIVED* ptr = new(place) DERIVED(static_cast(*this)); + return ptr; + } + + /** + * Destroy and deallocate this object, only if it was originally allocated using clone_(). + */ + virtual void deallocate_() const { + this->~DerivedValue(); // Virtual destructor cleans up the derived object + boost::singleton_pool::free((void*)this); // Release memory from pool + } + + /** + * Clone this value (normal clone on the heap, delete with 'delete' operator) + */ + virtual boost::shared_ptr clone() const { + return boost::make_shared(static_cast(*this)); + } + + /// equals implementing generic Value interface + virtual bool equals_(const Value& p, double tol = 1e-9) const { + // Cast the base class Value pointer to a derived class pointer + const DERIVED& derivedValue2 = dynamic_cast(p); + + // Return the result of calling equals on the derived class + return (static_cast(this))->equals(derivedValue2, tol); + } + + /// Generic Value interface version of retract + virtual Value* retract_(const Vector& delta) const { + // Call retract on the derived class + const DERIVED retractResult = (static_cast(this))->retract(delta); + + // Create a Value pointer copy of the result + void* resultAsValuePlace = boost::singleton_pool::malloc(); + Value* resultAsValue = new(resultAsValuePlace) DERIVED(retractResult); + + // Return the pointer to the Value base class + return resultAsValue; + } + + /// Generic Value interface version of localCoordinates + virtual Vector localCoordinates_(const Value& value2) const { + // Cast the base class Value pointer to a derived class pointer + const DERIVED& derivedValue2 = dynamic_cast(value2); + + // Return the result of calling localCoordinates on the derived class + return (static_cast(this))->localCoordinates(derivedValue2); + } + + /// Assignment operator + virtual Value& operator=(const Value& rhs) { + // Cast the base class Value pointer to a derived class pointer + const DERIVED& derivedRhs = dynamic_cast(rhs); + + // Do the assignment and return the result + return (static_cast(this))->operator=(derivedRhs); + } + + /// Conversion to the derived class + operator const DERIVED& () const { + return static_cast(*this); + } + + /// Conversion to the derived class + operator DERIVED& () { + return static_cast(*this); + } + +protected: + /// Assignment operator, protected because only the Value or DERIVED + /// assignment operators should be used. + DerivedValue& operator=(const DerivedValue& rhs) { + // Nothing to do, do not call base class assignment operator + return *this; + } + +private: + /// Fake Tag struct for singleton pool allocator. In fact, it is never used! + struct PoolTag { }; + +}; + +} /* namespace gtsam */