#ifndef __JLANG__JTEMPLATE__ #define __JLANG__JTEMPLATE__ #include #include #include "JLang/JTypeList.hh" #include "JLang/JConversion.hh" #include "JLang/JConstructor.hh" #include "JLang/JBool.hh" /** * \file * * Auxiliary class to alleviate the diamond problem due to multiple inheritance. * \author mdejong */ namespace JLANG {} namespace JPP { using namespace JLANG; } namespace JLANG { /** * Auxiliary class for managing multiple objects. * * This class can be used to replace regular base classes by corresponding data members. * The various operators and methods facilitate the access to these data members. * * The template value use_polymorfism in methods get and set * applies to the given template parameter of these methods. * If false, only exact type matches are allowed. * If true, * method get will return a reference to the first data member * of which the type derives from the specified class and * method set will assign the given value to the first data member * for which a matching constructor exists. */ template struct JTemplate { typedef JTemplate template_type; /** * Default constructor. */ JTemplate() : object() {} /** * Constructor. * * \param value value */ JTemplate(const JType_t& value) : object(value) {} /** * Type conversion. * * \return reference to object */ inline operator const JType_t&() const { return object; } /** * Type conversion. * * \return reference to object */ inline operator JType_t&() { return object; } /** * Smart pointer operator. * * \return pointer to object */ const JType_t* operator->() const { return &object; } /** * Smart pointer operator. * * \return pointer to object */ JType_t* operator->() { return &object; } /** * Get reference to object * * \return reference to object */ template const T& get() const { return this->c_get(JBool().template c_switch::is_derived, JConversion::is_same>()); } /** * Get reference to object * * \return reference to object */ template T& get() { return this->c_get(JBool().template c_switch::is_derived, JConversion::is_same>()); } /** * Set value. * * \param value value * \return this object */ inline template_type& set(const JType_t& value) { return c_set(value, JBool()); } /** * Set value. * * \param value value * \return this object */ template inline template_type& set(const T& value) { return this->c_set(value, JBool::template c_switch::has_constructor, JConversion::is_same>()); } /** * Read object from input. * * \param in input stream * \param object object * \return input stream */ friend inline std::istream& operator>>(std::istream& in, JTemplate& object) { return in >> object.object; } /** * Write object to output. * * \param out output stream * \param object object * \return output stream */ friend inline std::ostream& operator<<(std::ostream& out, const JTemplate& object) { return out << object.object; } protected: /** * Get reference to object * * \param option true * \return reference to object */ const JType_t& c_get(JBool option) const { return object; } /** * Get reference to object * * \param option true * \return reference to object */ JType_t& c_get(JBool option) { return object; } /** * Set value. * * \param value value * \param option true * \return this object */ template inline template_type& c_set(const T& value, JBool option) { object = value; return *this; } JType_t object; //!< object }; /** * Auxiliary class for managing multiple objects. */ template struct JTemplate< JTypeList > : public JTemplate, public JTemplate { typedef JTemplate< JTypeList > template_type; /** * Default constructor. */ JTemplate() : JTemplate(), JTemplate() {} /** * Constructor. * * \param head value * \param tail value */ JTemplate(const JHead_t& head, const JTail_t& tail) : JTemplate(head), JTemplate(tail) {} /** * Get reference to object * * \return reference to object */ template const T& get() const { return this->c_get(JBool().template c_switch::is_derived, JConversion::is_same>()); } /** * Get reference to object * * \return reference to object */ template T& get() { return this->c_get(JBool().template c_switch::is_derived, JConversion::is_same>()); } /** * Set value. * * \param value value * \return this object */ template inline template_type& set(const T& value) { return this->c_set(value, JBool::template c_switch::has_constructor, JConversion::is_same>()); } /** * Set value. * * \param value value * \return this object */ template inline template_type& set(const T& value) { return this->c_set(value, JBool::template c_switch::has_constructor, JConversion::is_same>()); } /** * Read object from input. * * \param in input stream * \param object object * \return input stream */ friend inline std::istream& operator>>(std::istream& in, JTemplate< JTypeList >& object) { return in >> static_cast&>(object) >> static_cast&>(object); } /** * Write object to output. * * \param out output stream * \param object object * \return output stream */ friend inline std::ostream& operator<<(std::ostream& out, const JTemplate< JTypeList >& object) { return out << static_cast&>(object) << ' ' << static_cast&>(object); } protected: /** * Get reference to object * * \param option true * \return reference to object */ template const T& c_get(JBool option) const { return static_cast&>(*this).template get(); } /** * Get reference to object * * \param option false * \return reference to object */ template const T& c_get(JBool option) const { return static_cast&>(*this).template get(); } /** * Get reference to object * * \param option true * \return reference to object */ template T& c_get(JBool option) { return static_cast&>(*this).template get(); } /** * Get reference to object * * \param option false * \return reference to object */ template T& c_get(JBool option) { return static_cast&>(*this).template get(); } /** * Set value. * * \param value value * \param option true * \return this object */ template inline template_type& c_set(const T& value, JBool option) { static_cast&>(*this).template set(value); return *this; } /** * Set value. * * \param value value * \param option false * \return this object */ template inline template_type& c_set(const T& value, JBool option) { static_cast&>(*this).template set(value); return *this; } }; /** * Auxiliary class for managing multiple objects. */ template struct JTemplate< JTypeList > : public JTemplate { /** * Default constructor. */ JTemplate() : JTemplate() {} /** * Constructor. * * \param value value */ JTemplate(const JHead_t& value) : JTemplate(value) {} }; } #endif