tags:

views:

259

answers:

2

Hi i am rewriting a project so that it uses getters and setters to reference the TiXmlElement *'s
However i quickly run into problems that seem to be related to debug mode:

ecxerpt from my class's header:

TiXmlElement *_rootElement; 
TiXmlElement *_dialogsElement; 
TiXmlElement *_dialogElement; 
TiXmlDocument _document; 
void setDocument (TiXmlDocument doc) { this->_document = doc; } 
void setRootElement (TiXmlElement * element) { this->_rootElement = element; } 
void setDialogsElement (TiXmlElement * element) { this->_dialogsElement = element; } 

TiXmlDocument getDocument () { return this->_document; } 
TiXmlElement* getRootElement () { return this->_rootElement; } 
TiXmlElement* getDialogsElement () { return this->_dialogsElement; }

except from class constructor:

DCXML::DCXML(const char *dialogMark,const char *dialogName,TiXmlDocument doc) { 
... 
this->setDocument(doc); 
this->setRootElement(this->getDocument().FirstChildElement("dcxml")); 
this->setDialogsElement(this->getRootElement()->FirstChildElement("dialogs"));

except from instantiating the class:

TiXmlDocument doc(input.gettok(2,"\"").to_chr()); 
bool dcxmlFile = doc.LoadFile(); 
... 
DCXML *dcxml = new DCXML(input.gettok(2).to_chr(),input.gettok(3).to_chr(),doc);

Now for the weird part this works up untill

this->setDialogsElement(this->getRootElement()->FirstChildElement("dialogs"));

in the constructor.

->FirstChildElement("dialogs") throws an "CXX0039: Error: symbol is ambiguous" error in VS2008 when in debug mode.

The weird part is intelisense picks up on the FirstChildElement method and the compiler doesn't throw any errors.

Whats even weirder is that when in release mode it just fails silently to get the dialogs element.

has anyone experienced this behaviour and/or know what i am doing wrong ? Or if you have succesfully implement getter setter wrappers for TiXmlElement*'s let me know how i can as well!.

For complete reference here's an except from the XML:

<?xml version="1.0" encoding="utf-8"?> 
<dcxml> 
<dialogs> 
<dialog name="mediaplayer" center="" w="300" h="400" caption="Mamp 4.0 BETA" border="btmnzy"> 
</dialog>
</dialogs>
</dcxml>

Feedback would be much appreciated as i am at a dead end :)

+2  A: 

Make sure that

TiXmlDocument getDocument () { return this->_document; }

Will not deep copy its contained TiXmlElement's. Otherwise you return a temporary, use that in the constructor to set the root node, which then will be destructed already. I haven't looked in its API, but just be aware of such pitfalls.

The reason for the ambiguous call is because:

There are three overloads of FirstChildElement taking one argument:

const TiXmlElement *    FirstChildElement (const char *value) const // :1
const TiXmlElement *    FirstChildElement (const std::string &_value) const // :2
TiXmlElement       *    FirstChildElement (const std::string &_value) // :3

You access the TiXmlElement through TiXmlElement& (using a TiXmlElement* pointer). But the version taking a const char* has an implicit object parameter of TiXmlElement const&. That is, a qualification conversion is required to make the call work. For the other versions taking a std::string const&, there are conversions required too:

<implied obj param> <implicit obj param>    <arg1>         <param1>
TiXmlElement&        TiXmlElement const&    char const*    char const*         // :1
TiXmlElement&        TiXmlElement const&    char const*    std::string const&  // :2
TiXmlElement&        TiXmlElement&          char const*    std::string const&  // :3

There is an ambiguity between the first and the third overload. An easy fix is to do

this->setDialogsElement(
    this->getRootElement()->FirstChildElement(std::string("dialogs")));

Instead, which will call the last version. Another fix is to const_cast:

this->setDialogsElement(
    const_cast<TiXmlElement const*>(this->getRootElement())->
        FirstChildElement("dialogs"));

Which will call the first version. As for why it only happens in DEBUG... I remember that TiXML has an option to disable the use of the STL. Maybe in release mode you disabled it (and thus the overloads taking std::string), but in debug mode you forgot?

Johannes Schaub - litb
A: 

BlockquoteTiXmlDocument getDocument () { return this->_document; } Will not deep copy its contained TiXmlElement's. Otherwise you return a temporary, use that in the constructor to set the root node, which then will be destructed already. I haven't looked in its API, but just be aware of such pitfalls.

Yeah moving that to the constructor was my next step :)

I can't believe i missed that! I had tried making the getters and setters return and take const TiXmlElement * values but that didn't work either.

Cant thank you enough for the help.

As for Debug Mode not disabling stl i'll have to look into that when i get back home from work. Can't wait to fix this issue thats been driving me nuts for the past 2 evenings eating up my sparse free time :D.

Martijn Laarman