'Can derived class member functions return different types than the base class?

I am running into a design issue with my code and I am not sure where to go. I am attempting to write a basic I/O class to write vectors of data into a text file for convenience in my research. In practice, I would like to not worry about the datatype in the array that I am writing to file and use the same interface regardless of if it is an array of ints, doubles, etc.

My basic idea was to create an AbstractColumn class, with a templated derived class to handle columns of different data. My I/O class could then contain an array of pointers to objects of this Abstract Class, and I can can add to this array as needed. See my header file below for the implementation of this.

#ifndef BASICIO_H
#define BASICIO_H

#include <vector>
#include <cstring>
#include <string>
#include <stdlib.h>

struct AbstractColumn{
    virtual ~AbstractColumn() = 0;
    template <class T> T* get_data(); // Issue comes in here, I think
    int nrows=0;
};

template <class T>
class Column : public AbstractColumn {
    public:
        Column(std::vector<T>& v);
        ~Column();
        T* get_data() {return data;}
        T* data;
        int nrows;
};

template <class T>
Column<T>::Column(std::vector<T>& v){
    nrows = v.size();
    data = static_cast<T*>(malloc(sizeof(T)*v.size())); //malloc returns void* so we need the static cast
    std::memcpy(data, v.data(), v.size());
}

template <class T>
Column<T>::~Column() {}

class BasicIO {
    public:
        BasicIO(std::string outname) : fname(outname), ncols(0) {}
        ~BasicIO();

        template <class T>
        void attach(std::vector<T>& v, std::string name="");
        void write();
        inline int get_ncols() {return ncols;}
        inline std::string filename() {return fname;}
    private:
        std::vector<AbstractColumn*> columns;
        std::vector<std::string> column_names;
        std::string fname;
        int ncols;
};

template <class T>
void BasicIO::attach(std::vector<T>& v, std::string name){
    Column<T>* col = new Column(v);
    columns.push_back(col);
    column_names.push_back(name);
}

#endif

My issue is coming in in trying to write the write() method that actually dumps this data to a file.

void BasicIO::write(){
// other formatting code here
    for(int i = 0; i<columns.at(0)->nrows; i++){
        for(int j = 0; j<ncols; j++){              
            outfile<<std::scientific<<std::left<<std::setw(col_width)<<(columns.at(j)->get_data())[i]<<" ";
        }                                                              //^ this is causing an error
        outfile<<std::endl;
    }
    outfile.close();
}

When I try to compile, I get the an error saying note: template argument deduction/substitution failed and couldn't deduce template parameter 'T'. Now, I think I understand what the issue is. When the compiler reaches this point, all it doesn't know what type of data is going to be returned by my get_data() function, since in the base class the return type is the template T. However, I don't see a way around this and I am very stuck. I have done a bit of reading and it seems like type erasure might be the way to go, but I also think I might be missing something simpler.

My Question All of the above context aside, my concrete question is as follows: What is the best way to have an array which holds objects (in this case columns) of generic types, specifically for the application described above? I am happy to offer any other details as needed, I just felt that my code snippets were already quite long. Thank you for reading.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source