Использование Boost посетителя для преобразования между типами - PullRequest
0 голосов
/ 27 октября 2011

Допустим, у меня есть

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

В этом объекте я храню данные из базы данных, которая обычно является целочисленной или текстовой, но иногда это время хранится в базе данных в виде текста. Поэтому мне интересно, смогу ли я создать посетителя, который при посещении варианта объекта со строкой в ​​нем возвращает структуру типа 'tm'. Примерно так:

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

Тогда, чтобы использовать его:

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

Дело в том, что я не хочу создавать структуру tm для посетителя и возиться с некоторыми общими указателями и прочим. Я предпочитаю отдавать уже созданный посетителю, а внутри просто для инициализации. Что-то вроде (в смысле использования):

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

Посетитель просто инициализирует с помощью strptime мой результат tm struct и даже вернет его, если возникла проблема с преобразованием в returnCode. Кто-нибудь знает, как этого можно достичь? Можно ли как-то определить посетителя, который принимает два параметра ... или, может быть, что-то еще?

Ответы [ 2 ]

1 голос
/ 27 октября 2011

В самом деле, это вполне допустимо, чтобы дать посетителю аргумент при создании. Код, который вы написали в конце вашего вопроса, является хорошим способом сделать это:

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

Вот как должен выглядеть посетитель: (не проверено на моей стороне, возможна небольшая синтаксическая ошибка)

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;
};
1 голос
/ 27 октября 2011

Ваш простой пример вызова должен работать. Добавьте к посетителю конструктор, который берет ссылку и сохраняет ее, например:

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