webentwicklung-frage-antwort-db.com.de

Boost-Variante: Wie bekomme ich den aktuell gehaltenen Typ?

Wie ich verstanden habe, werden alle Arten von boost.variant in reelle Typen zerlegt (was bedeutet, als ob boost variant<int, string> a; a="bla-bla" würde nach Zusammenstellung zu string a; a="bla-bla") Und so frage ich mich: woher kommt welcher Typ in die Boost-Variante?

Was habe ich versucht:

#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() gibt den 0-basierten Index des Typs des aktuell gehaltenen Objekts zurück.

Wenn Sie das Objekt abrufen, muss Ihr Code einen statischen Typ verwenden (um die Funktionsvorlage get<T> Zu erfüllen), um auf ein (effektiv) dynamisch typisiertes Objekt zu verweisen.

Sie müssen entweder den Typ testen (mit which() oder type()) und entsprechend verzweigen oder einen statischen Besucher verwenden. Unabhängig davon, auf welche Weise Sie sich entscheiden, müssen Sie den abzurufenden statischen Typ explizit angeben, und er muss mit dem dynamischen Typ übereinstimmen. Andernfalls wird eine Ausnahme ausgelöst.

Eine Möglichkeit, dieses Problem zu umgehen, besteht darin, anstatt einen Variantentyp direkt zu verwenden, eine Klasse zu verwenden, die intern einen Variantentyp enthält, und dann alle impliziten Konvertierungsoperatoren zu definieren, die erforderlich sind, um das Objekt mit minimalem Aufwand zu verwenden.

Ich habe ein Projekt namens Dynamic C++ , das diese Technik verwendet.

32
Ferruccio

boost.variant Hat eine .type() function , die die Typ-ID des aktiven Typs zurückgeben kann, vorausgesetzt, Sie haben RTTI aktiviert.

Sie können auch einen statischen Besucher definieren, der abhängig von der Art des Inhalts der Variante Aktionen ausführt, z.

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

Sie können Folgendes verwenden, das beide zu std :: type_info-Objekten führt:

  • die type () - Mitgliedsfunktion von boost :: variant,
  • den C++ - Operator typeid (), der auf einen beliebigen Typ oder typisierten Ausdruck angewendet werden kann,

zusammen mit der Member-Funktion std :: type_info :: operator == können Sie überprüfen, welchen Typ die boost :: -Variante gerade speichert. Beispielsweise,

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