December 21st, 2012, 12:15 AM
#1
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
December 21st, 2012, 04:56 PM
#2
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?
December 21st, 2012, 08:04 PM
#3
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 10:25 PM .
December 22nd, 2012, 05:21 AM
#4
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
December 22nd, 2012, 05:21 PM
#5
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
Forum Rules
Click Here to Expand Forum to Full Width
Bookmarks