c++ बूस्ट संस्करण: वर्तमान में आयोजित प्रकार कैसे प्राप्त करें?




boost boost-variant (3)

जैसा कि मैंने समझा कि सभी प्रकार के boost.variant को वास्तविक प्रकारों में पार्स किया गया है (जिसका अर्थ है कि बूस्ट variant<int, string> a; a="bla-bla" संकलन के बाद string a; a="bla-bla" में बदल जाएगा string a; a="bla-bla" ) और इसलिए मुझे आश्चर्य है: कैसे प्राप्त करें कि किस प्रकार को बढ़ावा संस्करण में रखा गया था?

मैंने क्या प्रयास किया है:

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

boost.variant में एक .type() फ़ंक्शन है जो सक्रिय प्रकार के टाइपिड को वापस कर सकता है, बशर्ते आपने RTTI सक्षम किया हो।

आप संस्करण की सामग्री के प्रकार के आधार पर कार्यों को करने के लिए एक स्थिर विज़िटर को भी परिभाषित कर सकते हैं, उदाहरण के लिए

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;

आप निम्न का उपयोग कर सकते हैं कि दोनों परिणाम std :: type_info ऑब्जेक्ट्स में:

  • boost :: variant का प्रकार () सदस्य फ़ंक्शन,
  • सी ++ ऑपरेटर टाइपिड () जिसे किसी भी प्रकार या टाइप की गई अभिव्यक्ति पर लागू किया जा सकता है,

सदस्य फ़ंक्शन std :: type_info :: ऑपरेटर == के साथ, यह देखने के लिए कि किस प्रकार boost :: variant वर्तमान में संग्रहीत है। उदाहरण के लिए,

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

v.which() वर्तमान में आयोजित ऑब्जेक्ट के प्रकार के 0-आधारित इंडेक्स को वापस कर देगा।

जब आप ऑब्जेक्ट को पुनर्प्राप्त कर रहे हैं तो आपके कोड को एक प्रभावी प्रकार (गतिशील) टाइप किए गए ऑब्जेक्ट को संदर्भित करने के लिए एक स्थिर प्रकार ( get<T> फ़ंक्शन टेम्पलेट को संतुष्ट करने के get<T> ) का उपयोग करना चाहिए।

आपको या तो प्रकार के लिए परीक्षण करना होगा ( which() उपयोग which() या type() ) और शाखा तदनुसार या एक स्थिर आगंतुक का उपयोग करें। इससे कोई फर्क नहीं पड़ता कि आप किस तरह से चुनते हैं, आपको उस स्थिर प्रकार को स्पष्ट रूप से अवश्य कहना है जिसे आप पुनर्प्राप्त करना चाहते हैं और इसे गतिशील प्रकार से मिलान करना होगा या अपवाद फेंक दिया जाएगा।

इस समस्या के आसपास एक तरीका सीधे एक प्रकार का उपयोग करने के बजाय है, एक वर्ग का उपयोग करें जिसमें एक प्रकार का प्रकार आंतरिक रूप से होता है और उसके बाद किसी भी अंतर्निहित रूपांतरण ऑपरेटर को न्यूनतम फस के साथ ऑब्जेक्ट का उपयोग करने के लिए आवश्यक परिभाषित करता है।

मेरे पास डायनामिक सी ++ नामक एक प्रोजेक्ट है जो इस तकनीक का उपयोग करता है।