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;
};

      

+3


source to share


2 answers


Yes, using Boost.Variant makes sense for this. However, you don't need to use pointers; instead:



boost::variant<Column<int>, Column<float>, Column<std::string>>

      

+1


source


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:

    Live On Coliru

    template <typename... Ts>
    using make_column_variant = typename boost::make_variant_over<boost::mpl::vector<Column<Ts>...>>::type;
    
          

    Here's the C ++ 03 version:

    Live On Coliru

    #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

+1


source







All Articles