2011-10-27 4 views
0

Disons que j'ai unutilisant visiteur boost pour convertir les types

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

Dans cet objet, je conserver des données à partir d'une base de données, qui est entier ou texte habituellement, mais est parfois un temps stocké dans la base de données texte. Donc, je me demande si je peux créer un visiteur, que lors de la visite de l'objet variant avec une chaîne, retourne une structure de type 'tm'. Quelque chose comme ça:

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

Ensuite, afin de l'utiliser:

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

La chose est que je ne veux pas créer la struct tm dans le visiteur et mess avec quelques conseils partagés et d'autres choses. Je préfère donner un déjà créé au visiteur et à l'intérieur juste pour être initialisé. Quelque chose comme (dans le sens de l'utilisation):

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

Le visiteur vient initialiser avec strptime mon résultat struct tm et même revenir s'il y avait un problème avec la conversion en returnCode. Est-ce que quelqu'un sait comment cela peut être réalisé? Puis-je définir en quelque sorte le visiteur qui prend deux paramètres ... ou peut-être quelque chose d'autre?

Répondre

1

Votre appel d'exemple simple devrait fonctionner. Ajouter un constructeur au visiteur qui prend une référence et le stocke, comme:

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

Ouais! Celui-là fonctionnait parfaitement ... Je savais que j'avais besoin d'un petit coup de pouce, mais ces bibliothèques de boost sont parfois un peu déroutantes. Ce que je ne savais pas, c'est que puisque j'ai boost :: variant , alors je dois aussi définir operator() qui prend int comme paramètre! Et à partir des messages d'erreur n'est pas très facile à trouver :( – pinpinokio

1

En effet, il est permis parfaitement de donner au visiteur un argument à la création. Le code que vous avez écrit à la fin de votre question est la bonne façon de le faire:

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

Voici comment le visiteur devrait ressembler à: (non testé sur mon côté, légère erreur de syntaxe 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; 
}; 
+0

Pourquoi construire un 'shared_ptr' lorsque vous avez déjà obtenu le résultat passé? – Xeo

+0

@Xeo: en effet, j'étais trop hâtif. – Offirmo

Questions connexes