I am trying to translate some Java code into C++ and I am having some trouble with the type system.
I have a interface/pure virtual class which represents a column in a table, and I want the table to be a vector of these generic columns:
template<typename T>
class IColumn {
public:
virtual const std::string& name() = 0;
virtual size_t size() = 0;
virtual T at(size_t idx) = 0;
virtual std::vector<T> data() = 0;
virtual ~IColumn() = default;
};
class StringColumn : public IColumn<std::string> {
public:
StringColumn(std::string name, std::vector<std::string> data)
: name_(std::move(name)), data_(std::move(data)) {}
const std::string& name() override { return name_; }
size_t size() override { return data_.size(); }
const std::vector<std::string>& data() override { return data_; }
std::string at(size_t idx) override { return data_[idx]; }
private:
std::string name_;
std::vector<std::string> data_;
};
class IntColumn : public IColumn<int> {
public:
IntColumn(std::string name, std::vector<int> data)
: name_(std::move(name)), data_(std::move(data)) {}
const std::string& name() override { return name_; }
size_t size() override { return data_.size(); }
const std::vector<int>& data() override { return data_; }
int at(size_t idx) override { return data_[idx]; }
private:
std::string name_;
std::vector<int> data_;
};
However, I am having issues when declaring the vector in the Table class:
class Table {
std::vector<std::unique_ptr<IColumn>> columns;
};
I understand that IColumn is a template class, hence it complains about the missing template parameter, however I am not sure how to get around this issue, because the virtual functions T at() and std::vector<T> data() rely on T.
How could I fix this issue or could someone suggest an alternative design for this API?
EDIT: Using the std::variant<IntColumn, StringColumn> with std::visit as suggested:
for (auto& col: columns_) {
std::cout << std::visit([](auto&& arg) { return arg.name(); }, col) << '\t';
}
std::cout << '\n';
for (int i = 0; i < this->rowCount(); i++) {
for (auto& col : columns_) {
auto v = std::visit([i](auto&& arg) { return arg.at(i); }, col);
std::cout << v;
}
}
The first std::visit works, but the second one doesn't.
Thanks.