Thread: A member variable that can be of any type.

  1. #1
    In the Land of Diddly-Doo g4j31a5's Avatar
    Join Date
    Jul 2006
    Posts
    476

    A member variable that can be of any type.

    Hi, I'm trying to make a simple xml reader that is using xerces. It can only read the data from xml tags and attributes. However I'm currently confused. Anyway this is my whole header so far:

    Code:
    // INCLUDES
    ...
    //FORWARD DECLARATION
    class CXmlReader;
    
    /**
     * @todo: add doxygen comments
     *
     */
    class CXmlAttribute  
    {
    	public:
    	////////////////////////////////////////////////////////////////////
    	// ENUM
    		/** 
    		 * @todo: add doxygen comments
    		 */
    		enum CXmlAttributeType
    		{
    			XML_ATTRIB_STRING,
    			XML_ATTRIB_BOOL,
    			XML_ATTRIB_INT,
    			XML_ATTRIB_FLOAT,
    			XML_ATTRIB_VEC2F,
    			XML_ATTRIB_VEC3F,
    			XML_ATTRIB_VEC4F
    		};
    
    	////////////////////////////////////////////////////////////////////
    	// METHODS
    		/** 
    		 * Get the Element Attribute
    		 * @todo: add more explanation
    		 */
    		std::string GetElementAttribute( xercesc::DOMElement& element
    										  , const std::string& attribName
    										  );
    
    		/** 
    		 * Get the Element Attribute as a string 
    		 * @todo: add more explanation
    		 */
    		bool GetAttribute( xercesc::DOMElement& element
    						 , const std::string& attribName
    						 , std::string& result
    						 , const std::string& defValue = ""
    						 );
    
    		/** 
    		 * Get the Element Attribute as a boolean 
    		 * @todo: add more explanation
    		 */
    		bool GetAttribute( xercesc::DOMElement& element
    						 , const std::string& attribName
    						 , bool& result
    						 , bool defValue = false
    						 );
    
    		/** 
    		 * Get the Element Attribute as a float 
    		 * @todo: add more explanation
    		 */
    		bool GetAttribute( xercesc::DOMElement& element
    						 , const std::string& attribName
    						 , float& result
    						 , float defValue = 0.0f
    						 );
    
    		/** 
    		 * Get the Element Attribute as an integer
    		 * @todo: add more explanation
    		 */
    		bool GetAttribute( xercesc::DOMElement& element
    						 , const std::string& attribName
    						 , int& result
    						 , int defValue = 0
    						 );
    
    		/** 
    		 * Get the Element Attribute as a vector 2f
    		 * @todo: add more explanation
    		 */
    		bool GetAttribute( xercesc::DOMElement& element
    						 , const std::string& attribName
    						 , CVec2f& result
    						 , const CVec2f& defValue = CVec2f()
    						 );
    
    
    		/** 
    		 * Get the Element Attribute as a vector 3f
    		 * @todo: add more explanation
    		 */
    		bool GetAttribute( xercesc::DOMElement& element
    						 , const std::string& attribName
    						 , CVec3f& result
    						 , const CVec3f& defValue = CVec3f()
    						 );
    
    
    		/** 
    		 * Get the Element Attribute as a vector 4f
    		 * @todo: add more explanation
    		 */
    		bool GetAttribute( xercesc::DOMElement& element
    						 , const std::string& attribName
    						 , CVec4f& result
    						 , const CVec4f& defValue = CVec4f()
    						 );
    	private:
    
    };
    
    /**
     * @todo: add doxygen comments
     *
     */
    class CXmlTag 
    {
    
    	public:
    		friend class CXmlReader;
    
    	////////////////////////////////////////////////////////////////////
    	// STRUCTS
    		/** 
    		 * @todo: add doxygen comments
    		 */
    		struct sAttribIdentifier
    		{
    			std::string								name;			///< The name of the attribute
    			CXmlAttribute::CXmlAttributeType		type;			///< The type of the attribute
    		};
    
    
    	////////////////////////////////////////////////////////////////////
    	// METHODS
    	
    		////////////////////////////////////////////////////////////////
    		// Constructor / Destructor
    		/** 
    		 * @todo: add doxygen comments
    		 */
    		CXmlTag(): mTagName("")
    		{
    			mAttribIdentifiers.clear();
    			mChildTags.clear();
    			mMemberAttribs.clear();
    		}
    
    		/** 
    		 * @todo: add doxygen comments
    		 */
    		CXmlTag(const std::string& tagName): mTagName(tagName)
    		{
    			mAttribIdentifiers.clear();
    			mChildTags.clear();
    			mMemberAttribs.clear();
    		}
    
    		/** 
    		 * @todo: add doxygen comments
    		 */
    		~CXmlTag()
    		{
    			mAttribIdentifiers.clear();
    			mChildTags.clear();
    			mMemberAttribs.clear();
    		}
    
    		////////////////////////////////////////////////////////////////
    		// Generic Methods
    		/** 
    		 * @todo: add doxygen comments
    		 */
    		bool ParseTagElement(xercesc::DOMElement *elem);
    
    		/** 
    		 * @todo: add doxygen comments
    		 */
    		void AddAttribIdentifier(sAttribIdentifier attribIdent);
    
    		/** 
    		 * @todo: add doxygen comments
    		 */
    		void SetTagName(const std::string& tagName);
    		/** 
    		 * @todo: add doxygen comments
    		 */
    		const std::string GetTagName() const;
    
    	protected:
    	////////////////////////////////////////////////////////////////////
    	// VARIABLES
    
    		std::string										mTagName;				///< The name / label of the tag
    		std::vector<sAttribIdentifier>				mAttribIdentifiers;		///< The vector that holds the type and name of the attributes that will be extracted from this tag. This should be unique.
    
    		std::vector<CXmlTag>							mChildTags;				///< The vector that holds the other tags that has become this tag's children
    		std::map<sAttribIdentifier, CXmlAttribute>		mAttributes;			///< The vector that holds the attributes data of this tag
    		
    	private:		
    };
    
    /**
     * @todo: add doxygen comments
     *
     */
    class CXmlReader
    {
    	public:
    	////////////////////////////////////////////////////////////////
    	//	CONSTANTS
    
    	////////////////////////////////////////////////////////////////////
    	// METHODS
    	
    		////////////////////////////////////////////////////////////////
    		// Constructor / Destructor
    	
    		/** 
    		 * @todo: add doxygen comments
    		 */
    		CXmlReader();
    
    		/** 
    		 * @todo: add doxygen comments
    		 */
    		~CXmlReader();
    
    		////////////////////////////////////////////////////////////////
    		// Generic methods
    		/** 
    		 * @todo: add doxygen comments
    		 */
    		bool LoadXML( const std::string& fileName
    					, const std::string& rootTagName = ""
    					, bool isCriticalError = false
    					);
    
    
    	
    	private:
    	////////////////////////////////////////////////////////////////////
    	// METHODS
    	
    		/** 
    		 * Parsing XML file 
    		 * @todo: add doxygen comments
    		 */
    		virtual bool ParseXML( const std::string& fileName
    							 , const std::string& rootTagName
    							 , bool isCriticalError 
    							 );
    
    
    	protected:
    	////////////////////////////////////////////////////////////////////
    	// VARIABLES
    		dtUtil::Log&					mLogger;				///< The logger object
    
    		std::string						mXmlFilePathName;		///< Full path filename of the xml file
    		std::string						mRootTagName;			///< The tag name (or label?) of the root (default: root)
    
    		bool							mIsCriticalError;		///< Is the XML critical or not? If true, throw critical exception on error. If not, just log the error.
    
    		xercesc::XercesDOMParser		mXmlParser;				///< Xerces parser
    		xercesc::DOMDocument			*mXmlDoc;				///< Xerces DOM document
    		xercesc::DOMElement				*mXmlRootDomElement;	///< The first Xerces DOM element (root element)
    
    		CXmlTag							mRootXmlTagData;		///< The root data extracted from the XML. 
    
    };
    As you can see in the CXmlAttribute class, there's no member variable at all. This is because I'm confused as what variable to use. FYI, the value of the attribute can be of any type that is enumerated with eXmlAttributeType. It is actually being read as a string from xerces so my initial plan is to store the string value and just translate it into the correct type using one of the GetAttribute() method. But that is not really efficient and I better store it into the correct type. So any suggestion of what I should use? Templates? Void pointers? Thanks in advance.
    ERROR: Brain not found. Please insert a new brain!

    “Do nothing which is of no use.” - Miyamoto Musashi.

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    The arguments to the various GetAttribute() member functions pass all information needed, so there is no need for the class to have any member variables.

    The function that, for example, accepts a reference to float as the third argument will interpret the XML element(s) as a float (and return the value in that third argument).
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  3. #3
    In the Land of Diddly-Doo g4j31a5's Avatar
    Join Date
    Jul 2006
    Posts
    476
    Well, that's true. But I kinda expect that the GetAttribute functions will only be used internally to set a member variable "mValue" that indicates the value of an attribute. That's because I want to minimize the overhead of parsing the tag for an attribute->converting the string from that parsed attribute using stringstream (yeah those GetAttribute functions are using stringstream to handle the conversion). So what I had in mind is parse the element once based on a tag's xercesc:OMElement object at the constructor (yea, just realized that I should've put the xercesc:OMElement& element as a parameter for the CXmlAttribute' ctor), then convert it to its type and store it into a variable called mValue (still dunno the type of this variable. a union of all those types? a template? or a void pointer? ). And afterwards, if the user wanted to extract this value, it can be done via a getter function GetValue().
    ERROR: Brain not found. Please insert a new brain!

    “Do nothing which is of no use.” - Miyamoto Musashi.

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Boost.Variant is such an union, except smarter, as it also knows what type it is storing, and allows access with compile-time visitors.

    I guess that would also allow you to implement all the GetAttribute methods as a single template.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Beginner Needs help in Dev-C++
    By Korrupt Lawz in forum C++ Programming
    Replies: 20
    Last Post: 09-28-2010, 01:17 AM
  2. Compiling Libraries in C
    By TheOriginalGame in forum C Programming
    Replies: 3
    Last Post: 08-15-2010, 11:19 AM
  3. Can you check what is wrong with this code
    By Ron in forum C++ Programming
    Replies: 4
    Last Post: 08-01-2008, 10:59 PM
  4. Using VC Toolkit 2003
    By Noobwaker in forum Windows Programming
    Replies: 8
    Last Post: 03-13-2006, 07:33 AM
  5. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM