Question

Let's say that I have a

boost::variant<std::string, int> myVariant;

In this object I keep data from a database, which is usually integer or text, but sometimes is a time stored in the database as text. So I wonder if I can create a visitor, that when visiting the variant object with a string into it, returns a struct of type 'tm'. Something like that:

class timeVisitor : public boost::static_visitor<boost::shared_ptr<tm> >
{
public:
    boost::shared_ptr<tm> operator()(string &str) const
    {
        boost::shared_ptr<tm> dst(new tm());
        strptime(str.c_str(), "%Y-%m-%d", dst.get());
        return dst;
    }
};

Then in order to use it:

boost::shared_ptr<tm> result = boost::apply_visitor( timeVisitor(), myVariant );

The thing is, that I don't want to create the tm struct into the visitor and mess around with some shared pointers and stuff. I prefer to give an already created one to the visitor and inside just to be initialized. Something like (in the sense of usage):

tm result;
int returnCode = boost::apply_visitor( timeVisitor(result), myVariant );

The visitor will just initialize with strptime my result tm struct and will even return if there was a problem with the conversion into returnCode. Does anyone know how this can be achieved? Can I define somehow visitor that take two parameters ... or maybe something else?

Was it helpful?

Solution

Your straightforward example call should work. Add a constructor to the visitor that takes a reference and stores it, like:

 tm* target;
 timeVisitor( tm& a ) : target(&a) {}
 int operator()(string &str) const {
      strptime(str.c_str(), "%Y-%m-%d", target);
 }

OTHER TIPS

Indeed, it's perfectly allowed to give the visitor an argument at creation. The code you wrote at the end of your question is the good way to do it :

tm result;
int returnCode = boost::apply_visitor( timeVisitor(result), myVariant );

Here is how the visitor should looks like : (not tested on my side, slight syntax error possible)

class timeVisitor : public boost::static_visitor<bool>
{
public:
    timeVisitor(tm& s):m_tm(s) {}

    bool operator()(string &str) const
    {
        return strptime(str.c_str(), "%Y-%m-%d", m_tm.get());
        // in case of error, NULL pointer is converted to false automatically
    }
protected:
    tm& m_tm;
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top