CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5
  1. #1
    Join Date
    Dec 2010
    Posts
    907

    Unresolved Externals for Template class.

    Code:
    // declaration
    template<class T>
    class GetValue
    {
        void Initialize(std::string fileName);
        
    };
    
    // definition
    template<class T>
    void GetValue<T>::Initialize(std::string fileName)
    {
    }
    
    // inheritance
    class GetD3DXVECTOR3 : public GetValue<D3DXVECTOR3>
    {
         
    };
    I understood that GetValue<D3DXVECTOR3>::Initialize was not defined. How can I reuse the GetValue::Initialize method in every derived classes from GetValue, such as GetD3DXVECTOR3, GetD3DXMATRIX, GetOpenGLVector3 etc
    Thanks
    Jack

  2. #2
    Join Date
    Aug 2009
    Location
    Romania->Felnac
    Posts
    48

    Re: Unresolved Externals for Template class.

    The only issue i see in the code you posted is that GetValue<T>::Initialize() is not public (or protected) but that shouldn't cause an undefined error, so are you using some "friend-based" mechanism to get to the method or what exactly are you doing? Can you post more code?

  3. #3
    Join Date
    Dec 2010
    Posts
    907

    Re: Unresolved Externals for Template class.

    Oh no, there still link time problem
    At first blush, I have put a public identifier in there.

    Code:
    #include <xercesc/dom/DOM.hpp>
    #include <xercesc/dom/DOMDocument.hpp>
    #include <xercesc/dom/DOMDocumentType.hpp>
    #include <xercesc/dom/DOMElement.hpp>
    #include <xercesc/dom/DOMImplementation.hpp>
    #include <xercesc/dom/DOMImplementationLS.hpp>
    #include <xercesc/dom/DOMNodeIterator.hpp>
    #include <xercesc/dom/DOMNodeList.hpp>
    #include <xercesc/dom/DOMText.hpp>
    
    #include <xercesc/parsers/XercesDOMParser.hpp>
    #include <xercesc/util/XMLUni.hpp>
    #include <string>
    #include <d3dx9.h>
    
    using namespace std;
    using namespace xercesc;
    
    template<class T>
    class GetValue
    {
    public:
    	GetValue() { }
    	~GetValue() {  }
    	
    	virtual T get(std::string element) = 0;
    
    	void Initialize(std::string filename);
    
    protected:
    	xercesc::XercesDOMParser* m_Parser;
    	xercesc::DOMDocument *doc;
    	
        XMLCh* TAG_root;
    
       
    };
    
    
    
    
     
    class GetD3DXVECTOR3 : public GetValue<D3DXVECTOR3>
    {
    public:
    	GetD3DXVECTOR3() { }
       ~GetD3DXVECTOR3() { }
    
    
    public:
       D3DXVECTOR3 get(std::string element);
    
    private:
       D3DXVECTOR3 m_Vec;
           
    };
    
    
    
     
     
    class GetD3DXMATRIX : public GetValue<D3DXMATRIX>
    {
    public:
    	GetD3DXMATRIX() { }
    	~GetD3DXMATRIX() { }
    
    public:
    	D3DXMATRIX get(std::string element);
    
    
    private:
    	D3DXMATRIX m_Mat;
    };
    Code:
    #include <Stdafx.h>
    #include <d3dx9.h>
    #include <iostream>
    #include <sstream>
    #include <boost/lexical_cast.hpp>
    #include "Parser.h"
     
    
    using namespace std;
    
    #define X(str) XStr(str).unicodeForm()
    
    
    template<class T>
    float ToFloat(const T& value)
    {
     
    	 
    	float f = boost::lexical_cast<float>(value); 
    	return f;
    	
    	
    }
    
     
    template<class T>
    void GetValue<T>::Initialize(std::string filename)
    {
    
    	try
       {
          XMLPlatformUtils::Initialize();  // Initialize Xerces infrastructure
       }
       catch( XMLException& e )
       {
          char* message = XMLString::transcode( e.getMessage() );
          cerr << "XML toolkit initialization error: " << message << endl;
          XMLString::release( &message );
          // throw exception here to return ERROR_XERCES_INIT
       }
    
       // Tags and attributes used in XML file.
       // Can't call transcode till after Xerces Initialize()
       TAG_root        = XMLString::transcode(X("BPS-Simulation-Format"));
        
       m_Parser = new XercesDOMParser;
       m_Parser->parse(filename.c_str());
    	 doc = m_Parser->getDocument();
    }
    
    
    D3DXVECTOR3 GetD3DXVECTOR3::get(std::string element)
    {
       try
       {
    	 
    	 DOMElement* elementRoot = doc->getDocumentElement();
         if( !elementRoot ) throw(std::runtime_error( "empty XML document" ));
    
          // Parse XML file for tags of interest: "ApplicationSettings"
          // Look one level nested within "root". (child of root)
    
          DOMNodeList*      children = elementRoot->getChildNodes();
          const  XMLSize_t nodeCount = children->getLength();
    
    	  for( XMLSize_t xx = 0; xx < nodeCount; ++xx )
          {
             DOMNode* currentNode = children->item(xx);
             if( currentNode->getNodeType() &&  // true is not NULL
                 currentNode->getNodeType() == DOMNode::ELEMENT_NODE ) // is element 
             {
                // Found node which is an Element. Re-cast node as element
                DOMElement* currentElement
                            = dynamic_cast< xercesc::DOMElement* >( currentNode );
    
    			XMLCh buff[100];
    			XMLString::transcode(element.c_str(), buff, 99);
                if( XMLString::equals(currentElement->getTagName(), buff))
                {
                   // Already tested node as type element and of name "ApplicationSettings".
                   // Read attributes of element "ApplicationSettings".
                   const XMLCh* xmlch_X
                         = currentElement->getAttribute(L"X");
                   m_Vec.x = ToFloat(XMLString::transcode(xmlch_X));
    
                   const XMLCh* xmlch_Y
                         = currentElement->getAttribute(L"Y");
                   m_Vec.y = ToFloat(XMLString::transcode(xmlch_Y));
    
    			   const XMLCh* xmlch_Z
                         = currentElement->getAttribute(L"Z");
                   m_Vec.z = ToFloat(XMLString::transcode(xmlch_Z));
    
    
                   break;  // Data found. No need to look at other elements in tree.
                }
             }
          }
       }
       catch( xercesc::XMLException& e )
       {
          char* message = xercesc::XMLString::transcode( e.getMessage() );
          std::ostringstream errBuf;
          errBuf << "Error parsing file: " << message << flush;
          XMLString::release( &message, xercesc_3_1::XMLPlatformUtils::fgMemoryManager );
       }
    
       return m_Vec;
    }
    
    D3DXMATRIX GetD3DXMATRIX::get(std::string element)
    {
    	  try
       {
    	 DOMElement* elementRoot = doc->getDocumentElement();
         if( !elementRoot ) throw(std::runtime_error( "empty XML document" ));
    
          // Parse XML file for tags of interest: "ApplicationSettings"
          // Look one level nested within "root". (child of root)
    
          DOMNodeList*      children = elementRoot->getChildNodes();
          const  XMLSize_t nodeCount = children->getLength();
    
    	  for( XMLSize_t xx = 0; xx < nodeCount; ++xx )
          {
             DOMNode* currentNode = children->item(xx);
             if( currentNode->getNodeType() &&  // true is not NULL
                 currentNode->getNodeType() == DOMNode::ELEMENT_NODE ) // is element 
             {
                // Found node which is an Element. Re-cast node as element
                DOMElement* currentElement
                            = dynamic_cast< xercesc::DOMElement* >( currentNode );
    
    			XMLCh buff[100];
    			XMLString::transcode(element.c_str(), buff, 99);
                if( XMLString::equals(currentElement->getTagName(), buff))
                {
                   // Already tested node as type element and of name "ApplicationSettings".
                   // Read attributes of element "ApplicationSettings".
                   const XMLCh* xmlch_11
                         = currentElement->getAttribute(L"_11");
                   m_Mat.m[0][0] = ToFloat(XMLString::transcode(xmlch_11));
    
                   const XMLCh* xmlch_12
                         = currentElement->getAttribute(L"_12");
                   m_Mat.m[0][1] = ToFloat(XMLString::transcode(xmlch_12));
    
    			   const XMLCh* xmlch_13
                         = currentElement->getAttribute(L"_12");
                   m_Mat.m[0][2] = ToFloat(XMLString::transcode(xmlch_13));
    
    			   const XMLCh* xmlch_14
                         = currentElement->getAttribute(L"_13");
                   m_Mat.m[0][3] = ToFloat(XMLString::transcode(xmlch_14));
    			   
    			   ////
    			   const XMLCh* xmlch_21
                         = currentElement->getAttribute(L"_21");
                   m_Mat.m[1][0] = ToFloat(XMLString::transcode(xmlch_21));
    
    			   const XMLCh* xmlch_22
                         = currentElement->getAttribute(L"_22");
                   m_Mat.m[1][1] = ToFloat(XMLString::transcode(xmlch_11));
    
    			   const XMLCh* xmlch_23
                         = currentElement->getAttribute(L"_23");
                   m_Mat.m[1][2] = ToFloat(XMLString::transcode(xmlch_23));
    
    			   const XMLCh* xmlch_24
                         = currentElement->getAttribute(L"_24");
                   m_Mat.m[1][3] = ToFloat(XMLString::transcode(xmlch_24));
    
    			   //
    			   const XMLCh* xmlch_31
                         = currentElement->getAttribute(L"_31");
                   m_Mat.m[2][0] = ToFloat(XMLString::transcode(xmlch_31));
    
    			   const XMLCh* xmlch_32
                         = currentElement->getAttribute(L"_32");
                   m_Mat.m[2][1] = ToFloat(XMLString::transcode(xmlch_32));
    
    			   const XMLCh* xmlch_33
                         = currentElement->getAttribute(L"_33");
                   m_Mat.m[2][2] = ToFloat(XMLString::transcode(xmlch_33));
    
    			   const XMLCh* xmlch_34
                         = currentElement->getAttribute(L"_34");
                   m_Mat.m[2][3] = ToFloat(XMLString::transcode(xmlch_34));
    
    
    			   //
    			   const XMLCh* xmlch_41
                         = currentElement->getAttribute(L"_41");
                   m_Mat.m[3][0] = ToFloat(XMLString::transcode(xmlch_41));
    
    			   const XMLCh* xmlch_42
                         = currentElement->getAttribute(L"_42");
                   m_Mat.m[3][1] = ToFloat(XMLString::transcode(xmlch_42));
    
    			   const XMLCh* xmlch_43
                         = currentElement->getAttribute(L"_43");
                   m_Mat.m[3][2] = ToFloat(XMLString::transcode(xmlch_43));
    
    			   const XMLCh* xmlch_44
                         = currentElement->getAttribute(L"_44");
                   m_Mat.m[3][3] = ToFloat(XMLString::transcode(xmlch_44));
    
    
    
    
    
    
    
                   break;  // Data found. No need to look at other elements in tree.
                }
             }
          }
       }
       catch( xercesc::XMLException& e )
       {
          char* message = xercesc::XMLString::transcode( e.getMessage() );
          std::ostringstream errBuf;
          errBuf << "Error parsing file: " << message << flush;
    	  XMLString::release( &message, xercesc_3_1::XMLPlatformUtils::fgMemoryManager );
       }
    
       return m_Mat;
    }
    Last edited by lucky6969b; December 21st, 2012 at 11:25 PM.

  4. #4
    Join Date
    Aug 2009
    Location
    Romania->Felnac
    Posts
    48

    Re: Unresolved Externals for Template class.

    Move the definition of Initialize into the header (that contains the declaration of GetValue<T>) and it should work, see this faq for more information: http://www.parashift.com/c++-faq/tem...n-vs-decl.html

  5. #5
    Join Date
    Dec 2010
    Posts
    907

    Re: Unresolved Externals for Template class.

    Thanks Zlatomir,
    That does the job nicely. Have a great Chrismtas holiday.

    Jack

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured