Comme exercice personnel, je veux implémenter le modèle de visiteur en utilisant shared_ptr. Je suis familier avec le journal acyclique de Robert Martin, mais je trouve la nature intrusive de la virtual accept() et la création nécessaire d'une classe {X} Visitor pour chaque classe {X} désagréable. J'aime la classe boost :: static_visitor car elle encapsule toute la logique localement sans la nécessité de {X} :: accept() et {X} Visitor. Ce que je cherche est un indice (comme je l'ai dit, je fais cela comme un exercice) de la façon de créer la fonction de fonction de modèle rip Je mentionne ci-dessous. Je pense qu'il devrait être de la forme:Métaprogrammation de template C++ pour créer un boost :: variant d'un shared_ptr et d'un boost :: static_visitor
template <typename U, typename T1, typename T2, ...>
boost::variant<T1, T2, ...> rip(U& p, boost::static_visitor<T1, T2, ...> sv)
{
if (T1 t1 = dynamic_cast<T1>(p)) return boost::variant<T1, ...>(t1);
... and so on, splitting static_visitor
return 0; // or throw an exception
}
Tout conseils ou des pointeurs vers des tutoriels qui font des choses semblables seraient appréciés. Merci.
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <boost/bind.hpp>
#include <boost/variant.hpp>
struct Base {};
struct A : Base {};
struct B : Base {};
struct C : Base {};
typedef std::shared_ptr<Base> base_ptr;
typedef boost::variant<A*,B*,C*> base_variant;
struct variant_visitor : public boost::static_visitor<void> {
void operator()(A*, base_ptr) const {std::cout << "A*\n";}
void operator()(B*, base_ptr) const {std::cout << "B*\n";}
void operator()(C*, base_ptr) const {std::cout << "C*\n";}
};
int main(int, char**)
{
// This works, of course.
base_ptr b(new A());
base_variant v(new A());
boost::apply_visitor(boost::bind(variant_visitor(), _1, b), v);
// How could we use a shared_ptr with a variant? I almost see
// the template magic, a function to iterate over the template
// types from the variant_visitor and return an "any<...>".
// base_variant rip(base_ptr&, variant_visitor) {...}
// boost::apply_visitor(boost::bind(variant_visitor(), _1, b), rip(b, variant_visitor()));
return EXIT_SUCCESS;
}
Merci pour la réponse. Voir mon commentaire à la solution d'UncleBen. Ce que je suis en train de jouer est comment convertir une base_ptr en une valeur sans nom, dont le seul but est d'agir en tant que discriminateur pour le variant_visitor :: operator(). La valeur n'est pas utilisée; l'opérateur() utilisera la base_ptr passée. –
themis
@themis: Donc la chose que vous cherchez est un moyen de ** downcast ** un pointeur de base vers un type de pointeur approprié dans une variante? J'ai ajouté quelque chose avec la bibliothèque du préprocesseur, mais j'aurais de gros doutes à ce sujet. Il a probablement des performances plutôt médiocres et peut donner de faux résultats si un type de base est listé avant le type le plus dérivé. – visitor