Should I use Boost Variant for a class with different type parameters
I'm new to C ++ and I'm not sure what is the best way to model a class to represent a table of columns; where column is a wrapper around an STL vector named (string) and must either be
Column<int>
, Column<float>
or Column<std::string>
.
At the moment I have tied it hard to Column<int>
, but have to support Column<float>
or Column<std::string>
.
Should I go down the route of the forced option (aka tagged union)?
boost::variant<Column<int>*, Column<float>*, Column<std::string>*>
Not sure if there is a better solution as it is just a type parameter that is different.
I would be grateful to the C ++ gods to share their wisdom.
template <typename T>
class Column
{
public:
Column(std::string& name, std::vector<T>& vec) : name(name), vec(vec) {}
T& at(const size_t i) { return vec[i]; }
private:
std::string name;
std::vector<T> vec;
};
class Table
{
public:
Table(std::string& name) : name{name} {}
void addColumn(Column<int>* vec)
{
columns.push_back(vec);
}
Column<int>*& getColumn(const size_t i)
{
return columns[i];
}
private:
std::string name;
std::vector<Column<int>*> columns;
};
source to share
If a variant suits your use case: a must! Template instances are just types.
-
You may be able to switch the design to something more than
Column<boost::variant<int, float, std::string>>
instead of this
-
You can create a variant from a list of types:
column_variant<int, float, std::string>
In C ++ 11, this is pretty trivial:
template <typename... Ts> using make_column_variant = typename boost::make_variant_over<boost::mpl::vector<Column<Ts>...>>::type;
Here's the C ++ 03 version:
#include <boost/variant.hpp> #include <boost/mpl/vector.hpp> #include <iostream> template <typename T> struct Column { T v; Column(T const& v) : v(v) {} friend std::ostream& operator<<(std::ostream& os, Column<T> const& cv) { return os << cv.v; } }; /* c++03 helper */ namespace mpl = boost::mpl; template <typename Seq> struct make_column_variant { typedef typename mpl::transform< Seq, Column<mpl::_1>, mpl::back_inserter<mpl::vector<> > >::type columns; typedef typename boost::make_variant_over<columns>::type type; }; int main() { make_column_variant<mpl::vector<int, float, std::string> >::type v(std::string("hello world")); std::cout << v; }
It could be significantly shorter in C ++ 11
source to share