web-dev-qa-db-fra.com

Variante Boost: comment obtenir le type actuellement détenu?

Comme je l'ai compris, tous les types de boost.variant sont analysés en types réels (ce qui signifie que si boost variant<int, string> a; a="bla-bla" se transformerait après la compilation en string a; a="bla-bla") Et donc je me demande: comment obtenir quel type a été mis en boost boost?

Qu'est-ce que j'ai essayé:

#include <boost/variant.hpp>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>

int main()
{
    typedef boost::function<double (double x)> func0;
    typedef boost::function<double (double x, double y)> func1;
    typedef boost::variant<int, func0, func1> variant_func;
    func1 fn = std::plus<double>();
    variant_func v(fn);
    std::cout << boost::get<func1>(v)(1.0, 1.0) << std::endl; // this works
    //std::cout << boost::get<v::type>(v)(1.0, 1.0) << std::endl; // this does not compile with many errors
    // std::cout << (v)(1.0, 1.0) << std::endl; // this fails with Error    1   error C2064: term does not evaluate to a function taking 2 arguments

    std::cin.get();
    return 0;
}
41
myWallJSON

v.which() renverra l'index basé sur 0 du type de l'objet actuellement détenu.

Lorsque vous récupérez l'objet, votre code doit utiliser un type statique (afin de satisfaire le modèle de fonction get<T>) Pour faire référence à un objet typé dynamiquement (efficacement).

Vous devez soit tester le type (en utilisant which() ou type()) et créer une branche en conséquence ou utiliser un visiteur statique. Peu importe la façon dont vous choisissez, vous devez indiquer explicitement le type statique que vous souhaitez récupérer et il doit correspondre au type dynamique ou une exception sera levée.

Une façon de contourner ce problème est au lieu d'utiliser directement un type variant, utilisez une classe qui contient un type variant en interne et définit ensuite les opérateurs de conversion implicites nécessaires pour utiliser l'objet avec un minimum de bruit.

J'ai un projet appelé Dynamic C++ qui utilise cette technique.

32
Ferruccio

boost.variant A un .type() fonction qui peut renvoyer l'ID de type du type actif, à condition que vous ayez activé RTTI.

Vous pouvez également définir un visiteur statique pour effectuer des actions en fonction du type de contenu de la variante, par exemple.

struct SomeVisitor : public boost::static_visitor<double>
{
    double operator()(const func0& f0) const { return f0(1.0); }
    double operator()(const func1& f1) const { return f1(1.0, 1.0); }
    double operator()(int integer) const { return integer; }
};
...
std::cout << boost::apply_visitor(SomeVisitor(), v) << std::endl;
18
kennytm

Vous pouvez utiliser les éléments suivants qui ont tous deux pour résultat des objets std :: type_info:

  • la fonction membre type () de boost :: variant,
  • l'opérateur C++ typeid () qui peut être appliqué à n'importe quel type ou expression typée,

avec la fonction membre std :: type_info :: operator ==, pour vérifier quel type la variante boost :: stocke actuellement. Par exemple,

boost::variant<int, bool, std::string> container;
container = "Hello world";

if (container.type() == typeid(std::string)) {
    std::cout << "Found a string: " << boost::get<std::string>(container);
}
else if (container.type() == typeid(int)) {
    std::cout << "Found an int: " << boost::get<int>(container);
}
10
richardr