Click here to Skip to main content
13,195,026 members (99,577 online)
Click here to Skip to main content
Add your own
alternative version


60 bookmarked
Posted 11 Aug 2000

Generic Serializer - serializing arbitrary data structures

, 11 Aug 2000
Rate this:
Please Sign up or sign in to vote.
Template functions for serializing arbitrary linked nodes.
  • Download demo project - 25 Kb
  • Download source - 3 Kb
  • Sample Image

    <!-- STEP 3. Add the article text.-->


    The methods in the MFC classes CObject and CArchive provide a framework for serialization but give no help when one has to serialize complex data structures containing cyclic references.

    The functions GenericSerialize and GenericDeserialize presented in this article implement a general serialization algorithm. These C++ template functions can handle any homogenous datastructure (datastructure consisting of nodes having all the same type).

    The user has to provide a so called Accessor class which is responsible for

    • defining a typedef name called Type which gives the type of a node pointer.
    • providing a member variable called ar which must be a reference to an archive object.
    • providing a member function Null() which returns the null value for Type
    • serializing and deserializing a single element.
    • returning the immediate neighbors of an element.


    template<class Access>
    void GenericSerialize(const Access& a);
    template<class Access>
    void GenericDeserialize(const Access& a);
    //The Access class must adhere to the following scheme
    struct MyAccess
        typedef MyPointerType Type;
        CArchive ar;
        Type   Null()
               {/*your code*/}
        void   GetNeighbors(Type current,vector< pair<Type,int/*nTyp*/> >& vecNeighbors)
               { /*your code */ }//GetNeighbors(Null(),.. ) must place all root elements
                                 // into <code>vecNeighbors</code>
        void   SerializeThis(Type owner,Type current,int nTyp)const	
               { /*your code/* }
        Type   DeserializeThis(Type owner,int nTyp)const
               { /*your code*/ }
        void   SetReference(Type owner,Type current,int nTyp)const
               { /*your code*/ }//current is an already deserialized reference of owner

    Example A - Serialization of a tree view control

    The demo project serializes a tree view control by a call to the following function.

    void CGenericSerializeDemoView::TreeSerialize(CArchive& ar)
        TreeAccess access(m_Tree,ar); //user defined part of serialization
        if (ar.IsStoring())
            GenericSerialize(access);//general algorithm for serialization
            GenericDeserialize(access); //general algorithm for deserialization

    The following Accessor class is the user provided part for the serialization of a tree view control.

    struct TreeAccess{//user part for tree ctrl serialization
        TreeAccess(CTreeCtrl& rTree,CArchive& rAr):tree(rTree),ar(rAr){}
        typedef HTREEITEM   Type;   //'Type' is a mandatory member of any Access class
    #define TA_eRoot       0
    #define TA_eChild      1
    #define TA_eSibling    2
        CTreeCtrl&  tree;   
        CArchive&   ar;     //'ar' is a mandatory member of any Access class
        HTREEITEM   Null()const    {return NULL;}
        void        GetNeighbors(HTREEITEM current,vector< pair<Type,int> >& vecNeighbors)
            if(current==NULL){//get root items
                HTREEITEM   hItem= tree.GetRootItem();
                    vecNeighbors.push_back( make_pair(hItem,TA_eRoot));
                HTREEITEM hItem= tree.GetNextSiblingItem(current);
                hItem= tree.GetChildItem(current);
        void    SerializeThis(HTREEITEM owner,HTREEITEM current,int nTyp)const
            ar  <<  tree.GetItemText(current);
            ar  <<  tree.GetItemState(current,TVIF_STATE);
        HTREEITEM    DeserializeThis(HTREEITEM owner,int nTyp)const
            CString strItemText;
            UINT   nState;
            ar  >> strItemText;
            ar  >> nState;
            HTREEITEM hItem;
            case TA_eRoot:     hItem= tree.InsertItem(strItemText);           break;
            case TA_eChild:    hItem= tree.InsertItem(strItemText,owner);     break;
            case TA_eSibling:  hItem= tree.InsertItem(strItemText,
                                        tree.GetParentItem(owner),owner);     break;
            return hItem;
        void    SetReference(HTREEITEM owner,HTREEITEM current,int nTyp)const

    Example B - Serialization of a general graph

    The following Accessor class is the user provided part for the serialization of a Graph consisting of nodes having the following definition

    struct Graph{ 
    	Graph(int x=0,int y=0):x(x),y(y){} 
    	int x,y; 
    	vector<Graph*> vecConnections;
    struct GraphAccess{//user part for graph serialization
        GraphAccess(vectorGraph& rGraph,CArchive& rAr):graph(rGraph),ar(rAr){}
        typedef Graph*   Type;      //'Type' is a mandatory member of any Access class
        vectorGraph&  graph;
        CArchive&       ar;         //'ar' is a mandatory member of any Access class
    #define GA_eRoot    0
    #define GA_eConnect 1
        Graph*  Null()const {return 0;}
        void    GetNeighbors(Graph* current,vector< pair<Type,int> >& vecNeighbors)const
            if(current==NULL){//get root items
                for(unsigned i=0;i<graph.size();i++){
                    vecNeighbors.push_back( make_pair(graph[i],GA_eRoot));
                for(unsigned i=0;i<current->vecConnections.size();i++){
                    vecNeighbors.push_back( make_pair(graph[i],GA_eConnect));
        void SerializeThis(Graph* owner,Graph* current,int nTyp)const
            ar  <<  current->x;
            ar  <<  current->y;
        Graph* DeserializeThis(Graph* owner,int nTyp)const
            int x,y;
            ar  >>  x;
            ar  >>  y;
            graph.push_back(new Graph(x,y));
            return graph[graph.size()-1];
        void SetReference(Graph* owner,Graph* current,int nTyp)const
            if(owner!=0 && nTyp==GA_eConnect){


    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here


    About the Author

    Martin Holzherr
    Switzerland Switzerland
    No Biography provided

    You may also be interested in...

    Comments and Discussions

    GeneralUnable to download Source Files Pin
    neeraj_sathe26-Jun-05 18:49
    memberneeraj_sathe26-Jun-05 18:49 
    Questionconverting a sequence of BMP to AVI ??? Pin
    mr20037-May-01 2:59
    membermr20037-May-01 2:59 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

    Permalink | Advertise | Privacy | Terms of Use | Mobile
    Web01 | 2.8.171018.2 | Last Updated 12 Aug 2000
    Article Copyright 2000 by Martin Holzherr
    Everything else Copyright © CodeProject, 1999-2017
    Layout: fixed | fluid