sigalor
sigalor

Reputation: 1379

pugixml error in nested class

I've got the following C++ code:

#include <ctime>
#include <vector>
#include <pugixml/pugixml.hpp>          //pugixml (version 1.6)

using namespace pugi;

class ClassA
{
    public:
        xml_document doc;

        void writeString(const char *str)
        {
            doc.append_child("randomString").append_child(node_pcdata).set_value(str);
        }
};

class ClassB
{
    private:
        class ClassB_Child
        {
            public:
                ClassA aInstance;
                long timestamp;

            public:
                ClassB_Child()
                {
                    timestamp = time(NULL);
                    aInstance.writeString("Hello world!");
                }
        };

    public:
        std::vector<ClassB_Child> vecBChild;

        ClassB()
        {
            vecBChild.push_back(ClassB_Child());
        }
};

int main()
{
    ClassB bInstance;

    return 0;
}

But every time I want to compile it (using MinGW g++ 4.8.1), just many errors are generated:

In file included from broken.cpp:3:0:
broken.cpp: In instantiation of 'void std::vector<_Tp, _Alloc>::_M_insert_aux(std::vector<_Tp, _Alloc>::iterator, const _Tp&) [with _Tp = ClassB::ClassB_Child; _Alloc = std::allocator<ClassB::ClassB_Child>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<ClassB::ClassB_Child*, std::vector<ClassB::ClassB_Child> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = ClassB::ClassB_Child*]':
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\stl_vector.h:913:28:   required from 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = ClassB::ClassB_Child; _Alloc = std::allocator<ClassB::ClassB_Child>; std::vector<_Tp, _Alloc>::value_type = ClassB::ClassB_Child]'
broken.cpp:40:38:   required from here
c:\mingw\include\pugixml\pugixml.hpp:941:3: error: 'pugi::xml_document::xml_document(const pugi::xml_document&)' is private
   xml_document(const xml_document&);
   ^
broken.cpp:7:7: error: within this context
 class ClassA
       ^
broken.cpp:21:9: note: synthesized method 'ClassA::ClassA(const ClassA&)' first required here 
   class ClassB_Child
         ^
In file included from c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\vector:69:0,
                 from broken.cpp:2:
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\vector.tcc:329:19: note: synthesized method 'ClassB::ClassB_Child::ClassB_Child(const ClassB::ClassB_Child&)' first required here 
    _Tp __x_copy = __x;
                   ^
In file included from broken.cpp:3:0:
c:\mingw\include\pugixml\pugixml.hpp:942:23: error: 'const pugi::xml_document& pugi::xml_document::operator=(const pugi::xml_document&)' is private
   const xml_document& operator=(const xml_document&);
                       ^
broken.cpp:7:7: error: within this context
 class ClassA
       ^
broken.cpp:21:9: note: synthesized method 'ClassA& ClassA::operator=(const ClassA&)' first required here 
   class ClassB_Child
         ^
In file included from c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\vector:69:0,
                 from broken.cpp:2:
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\vector.tcc:335:16: note: synthesized method 'ClassB::ClassB_Child& ClassB::ClassB_Child::operator=(const ClassB::ClassB_Child&)' first required here 
    *__position = __x_copy;
                ^

I also encountered, that all the errors disappear when I delete the pugi::xml_document doc; line (then the program compiles and runs fine). That means, the error has to be caused by pugixml. What do I have to change in my code to let the program compile properly?

Upvotes: 0

Views: 619

Answers (1)

Toby Speight
Toby Speight

Reputation: 30860

The first error explains your problem, albeit cryptically:

pugixml.hpp: In member function 'ClassA::operator=(const ClassA&)':

The compiler is trying to synthesize a default assignment operator for you. The default implementation will assign each member of the destination ClassA from the corresponding member in the source ClassA. In this case, it will look as if you had

ClassA::operator=(const ClassA& other)
{
    doc = other.doc;
}

When it gets to trying to copy the doc member, it finds that it's not allowed to copy it:

pugixml.hpp:942:23: error: 'const pugi::xml_document& pugi::xml_document::operator=(const pugi::xml_document&)' is private

The inability to copy doc means that we can't copy a ClassA; in turn that means we can't copy a ClassB_Child, and that in its turn prevents declaration of a std::vector of ClassB_Child.

In order to solve your problem, you need to decide what you want to happen when you copy a class containing an xml_document. If there's a means of providing the right kind of copy (a deep copy, probably), then create an appropriate assignment operator (and a corresponding copy constructor and probably a destructor - search for the "rule of three" or even "rule of five" or "rule of zero" on the Web). Or perhaps you want to share a single XML document?

Upvotes: 0

Related Questions