खोज…


टिप्पणियों

वेरिएंट कच्चे union उपयोग के लिए एक प्रतिस्थापन है। यह प्रकार-सुरक्षित है और जानता है कि यह किस प्रकार का है, और यह ध्यान से वस्तुओं का निर्माण और विनाश करता है जब यह होना चाहिए।

यह लगभग कभी खाली नहीं होता है: केवल कोने के मामलों में जहां इसकी सामग्री फेंकता है और यह सुरक्षित रूप से वापस नहीं हो सकता है यह खाली स्थिति में समाप्त होता है।

यह कुछ हद तक एक std::tuple तरह व्यवहार करता है, और कुछ std::optional

std::get और std::get_if का उपयोग करना आमतौर पर एक बुरा विचार है। सही उत्तर आमतौर पर std::visit , जो आपको हर संभावना से निपटने का मौका देता है। if constexpr का उपयोग visit भीतर किया जा सकता है, यदि आपको अपने व्यवहार को शाखा देने की आवश्यकता है, बजाय रनटाइम चेक के एक अनुक्रम करने के लिए जो नकल करता है कि visit अधिक कुशलता से क्या करेगी।

मूल std :: भिन्न उपयोग

यह एक वैरिएंट (एक टैग की गई यूनियन) बनाता है जो int या string को स्टोर कर सकता है।

std::variant< int, std::string > var;

हम इसमें से किसी एक प्रकार को स्टोर कर सकते हैं:

var = "hello"s;

और हम std::visit माध्यम से सामग्री का उपयोग कर सकते हैं std::visit :

// Prints "hello\n":
visit( [](auto&& e) {
  std::cout << e << '\n';
}, var );

एक बहुरूपी लैम्ब्डा या इसी तरह के फ़ंक्शन ऑब्जेक्ट में गुजरने से।

यदि हम निश्चित हैं तो हमें पता है कि यह किस प्रकार का है, हम इसे प्राप्त कर सकते हैं:

auto str = std::get<std::string>(var);

लेकिन अगर यह गलत हुआ तो हम इसे फेंक देंगे। get_if :

auto* str  = std::get_if<std::string>(&var);

यदि आप गलत अनुमान nullptr तो nullptr देता है।

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

वेरिएंट आपको एक चर में कई मूल्य प्रकारों को सुरक्षित और कुशलता से संग्रहीत करने देता है। वे मूल रूप से स्मार्ट हैं, टाइप-सेफ union एस।

छद्म विधि संकेत बनाएँ

यह एक उन्नत उदाहरण है।

आप हल्के वजन प्रकार के क्षरण के लिए संस्करण का उपयोग कर सकते हैं।

template<class F>
struct pseudo_method {
  F f;
  // enable C++17 class type deduction:
  pseudo_method( F&& fin ):f(std::move(fin)) {}

  // Koenig lookup operator->*, as this is a pseudo-method it is appropriate:
  template<class Variant> // maybe add SFINAE test that LHS is actually a variant.
  friend decltype(auto) operator->*( Variant&& var, pseudo_method const& method ) {
    // var->*method returns a lambda that perfect forwards a function call,
    // behaving like a method pointer basically:
    return [&](auto&&...args)->decltype(auto) {
      // use visit to get the type of the variant:
      return std::visit(
        [&](auto&& self)->decltype(auto) {
          // decltype(x)(x) is perfect forwarding in a lambda:
          return method.f( decltype(self)(self), decltype(args)(args)... );
        },
        std::forward<Var>(var)
      );
    };
  }
};

यह एक प्रकार बनाता है जो operator->* ओवरलोड operator->* बाएं हाथ पर एक Variant साथ।

// C++17 class type deduction to find template argument of `print` here.
// a pseudo-method lambda should take `self` as its first argument, then
// the rest of the arguments afterwards, and invoke the action:
pseudo_method print = [](auto&& self, auto&&...args)->decltype(auto) {
  return decltype(self)(self).print( decltype(args)(args)... );
};

अब अगर हमारे पास print विधि के साथ 2 प्रकार हैं:

struct A {
  void print( std::ostream& os ) const {
    os << "A";
  }
};
struct B {
  void print( std::ostream& os ) const {
    os << "B";
  }
};

ध्यान दें कि वे असंबंधित प्रकार हैं। हम कर सकते हैं:

std::variant<A,B> var = A{};

(var->*print)(std::cout);

और यह कॉल को सीधे हमारे लिए A::print(std::cout) भेज देगा। यदि हमने इसके बजाय B{} साथ var को इनिशियलाइज़ किया है, तो यह B::print(std::cout) लिए प्रेषण करेगा।

यदि हमने एक नया प्रकार C बनाया है:

struct C {};

फिर:

std::variant<A,B,C> var = A{};
(var->*print)(std::cout);

संकलित करने में विफल रहेगा, क्योंकि कोई C.print(std::cout) विधि नहीं है।

उपरोक्त का विस्तार करने से नि: शुल्क फ़ंक्शन print एस का पता लगाया जा सकता है और इसका उपयोग किया जा सकता है, संभवत: if constexpr print छद्म पद्धति के भीतर if constexpr का उपयोग किया जाता है।

लाइव उदाहरण वर्तमान में boost::variant std::variant स्थान पर std::variant

एक `एसटीडी :: संस्करण` का निर्माण

यह आवंटनकर्ताओं को कवर नहीं करता है।

struct A {};
struct B { B()=default; B(B const&)=default; B(int){}; };
struct C { C()=delete; C(int) {}; C(C const&)=default; };
struct D { D( std::initializer_list<int> ) {}; D(D const&)=default; D()=default; };

std::variant<A,B> var_ab0; // contains a A()
std::variant<A,B> var_ab1 = 7; // contains a B(7)
std::variant<A,B> var_ab2 = var_ab1; // contains a B(7)
std::variant<A,B,C> var_abc0{ std::in_place_type<C>, 7 }; // contains a C(7)
std::variant<C> var_c0; // illegal, no default ctor for C
std::variant<A,D> var_ad0( std::in_place_type<D>, {1,3,3,4} ); // contains D{1,3,3,4}
std::variant<A,D> var_ad1( std::in_place_index<0> ); // contains A{}
std::variant<A,D> var_ad2( std::in_place_index<1>, {1,3,3,4} ); // contains D{1,3,3,4}


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow