Search code examples
c++functiongenericsreturnvirtual

Return Generic Type data from function


I have written the following code. Where the function func() print the header and data.

class ICell
{
    public:
        wstring header;
        virtual void Fetch() = 0;
};

template <class T>
class Cell : public ICell
{
public:
    //wstring header;
    T data;
    void Fetch()
    {
        wcout<< header << L": ";
        cout<<data<<endl;
    }
  // implementation of cell methods
};

class Row
{
public:
  vector <ICell *> cells;
};

Is there any way to return the data instead of print within the function? If so, which portion of the code should be modified? Thanks in advance.

int main()
{
    Cell<int>c1;
    Cell<double>c2;

    c1.header = L"Roll", c1.data = 100;
    c2.header = L"CGPA", c2.data = 3.5;

    Row r;
    r.cells.push_back(&c1);
    r.cells.push_back(&c2);

    vector <ICell *>::iterator it;
    for(it=r.cells.begin();it!=r.cells.end();it++)
    {
        //checkt type of it wherther it points Cell<int> or Cell<double>
    }

    return 0;
}

I have changed my question here. In main() inside the loop how can I check the object type which is pointed by 'it'?

Thank you all for patience and helping me :)


Solution

  • Easiest way is to use dynamic_cast:

    vector <ICell *>::iterator it;
    for(it=r.cells.begin();it!=r.cells.end();it++)
    {
        Cell<int>* cell_i= dynamic_cast<Cell<int>*>(*it);
        if(cell_i)
        {
           do_something(cell_i->data);
           continue;
        }
    
        Cell<double>* cell_d= dynamic_cast<Cell<double>*>(*it);
        if(cell_d)
        {
           do_something(cell_d->data);
           continue;
        } 
    }
    

    Better way is to use visitor pattern:

    class ICellVisitor; //declaration for ICell to understand ICell* pointer
    class ICell
    {   public:
        ~ICell(){}; // important
        std::wstring header;
        virtual void visit( ICellVisitor* v ) = 0;
    };
    template <class T> class Cell; // for Cell<T>* pointer
    class ICellVisitor
    {   public:
        virtual void visit( Cell<int>* c ) = 0;
        virtual void visit( Cell<double>* c ) = 0;
        virtual void visit( Cell<float>* c ) = 0;
        virtual void visit( Cell<long long>* c ) = 0;
    };
    template <class T> class Cell : public ICell
    {   public:
        //wstring header;
        T data;
        void visit( ICellVisitor* v )
        {
            std::wcout<< header << L": ";
            v->visit(this);
        }
      // implementation of cell methods
    };
    class Row
    { public:
      std::vector <ICell *> cells;
    };
    

    Now we need definition of concrete visitor to keep the algorithm for each type:

    class MyCellVisitor: public ICellVisitor
    {   public:
        void visit( Cell<int>* c ){ 
            std::wcout<<"(int)"<<c->data<<std::endl; 
        }
        void visit( Cell<double>* c ){ 
            std::wcout<<"(double)"<<c->data<<std::endl;
        }
        void visit( Cell<float>* c ){ 
            std::wcout<<"(float)"<<c->data<<std::endl;
        }
        void visit( Cell<long long>* c ){ 
            std::wcout<<"(long long)"<<c->data<<std::endl;
        }
    };
    
    int main()
    {
        Cell<int>c1;
        Cell<double>c2;
        c1.header = L"Roll", c1.data = 100;
        c2.header = L"CGPA", c2.data = 3.5;
        Row r;
        r.cells.push_back(&c1);
        r.cells.push_back(&c2);
        MyCellVisitor visitor;
        std::vector <ICell *>::iterator it;
        for(it=r.cells.begin();it!=r.cells.end();it++)
        {
            (*it)->visit( &visitor );
        }
        return 0;
    }