C++ लैंबडा का टर्नरी असाइनमेंट




c++11 lambda (4)

उत्सुकता से, यदि लंबोदर कैप्चर-कम हैं, तो ऑपरेटर + चाल को नियोजित किया जा सकता है:

auto lambda1 = [](int arg) { ... };
auto lambda2 = [](int arg) { ... };

auto lambda = condition ? +lambda1 : +lambda2; // This compiles!
lambda(2019); 

यह काम करता है, क्योंकि + लैम्ब्डा को एक फ़ंक्शन पॉइंटर में बदल देगा, और दोनों फ़ंक्शन पॉइंटर्स का एक ही प्रकार ( void (*)(int) जैसा कुछ है)।

जीसीसी और क्लैंग (लेकिन एमएसवीसी के साथ नहीं) के साथ, + छोड़ा जा सकता है, लैम्बडा को अभी भी फ़ंक्शन पॉइंटर्स में परिवर्तित किया जाएगा।

किसी भी विचार क्यों निम्नलिखित स्निपेट संकलन नहीं करता है? यह एक त्रुटि के साथ शिकायत करता है "त्रुटि: ऑपरेंड ?: विभिन्न प्रकार हैं"

  auto lambda1 = [&](T& arg) {
      ...
  };
  auto lambda2 = [&](T& arg) {
      ...
  };
  auto lambda = condition ? lambda1 : lambda2;

कंपाइलर यह तय नहीं कर सकता है कि auto किस प्रकार का होना चाहिए:

auto lambda = condition ? lambda1 : lambda2;

चूंकि हर मेमने का एक अलग और अनोखा प्रकार होता है।

एक तरीका है कि काम करेंगे:

auto lambda = [&](T& arg) {
     return (condition ? lambda1(arg) : lambda2(arg));
}

यह संकलित नहीं करता है क्योंकि प्रत्येक लंबोदर के पास एक अद्वितीय प्रकार है, इसके लिए एक सामान्य प्रकार नहीं है ?:

आप उन्हें std::function<void(T&)> , जैसे में लपेट सकते हैं

auto lamba1 = [&](T& arg) {
  ...
};
auto lambda2 = [&](T& arg) {
  ...
};
auto lambda = condition ? std::function(lambda1) : lambda2; // C++17 class template deduction

संकलक द्वारा अलग-अलग कक्षाओं में इंडिविजुअल लैम्ब्डा का अनुवाद किया जाता है। lambda1 की परिभाषा इसके बराबर है:

class SomeCompilerGeneratedTypeName {
public:
  SomeCompilerGeneratedTypeName(...) { // Capture all the required variables here
  }

  void operator()(T& arg) const {
    // ...
  }

private:
  // All the captured variables here ...
};

इसलिए, संकलक द्वारा दो अलग-अलग प्रकार उत्पन्न होते हैं इस प्रकार auto lambda = condition ? lambda1 : lambda2; लिए एक प्रकार की असंगति auto lambda = condition ? lambda1 : lambda2; auto lambda = condition ? lambda1 : lambda2;

निम्नलिखित काम करेगा:

auto lambda = condition ? std::function<void(T&)>(lambda1) : std::function<void(T&)>(lambda2);

यह उजागर करने के लिए कि दोनों <typeinfo> वास्तव में अलग-अलग प्रकार के हैं, हम मानक पुस्तकालय और typeid ऑपरेटर से <typeinfo> उपयोग कर सकते हैं। क्योंकि लैम्ब्डा typeid प्रकार नहीं हैं, इसलिए मानक गारंटी देता है कि typeid ऑपरेटर का संकलन-समय पर मूल्यांकन किया जाता है, इसलिए typeid अक्षम होने पर भी निम्न उदाहरण मान्य है।

#include <iostream>
#include <typeinfo>

int main()
{
    struct T {

    };

    auto lambda1 = [&](T& arg) {
        return;
    };

    auto lambda2 = [&](T& arg) {
      return;
    };

    std::cout << typeid(lambda1).name() << "/" << typeid(lambda1).hash_code() << std::endl;
    std::cout << typeid(lambda2).name() << "/" << typeid(lambda2).hash_code() << std::endl;

    return 0;
}

कार्यक्रम का आउटपुट (GCC 8.3 के साथ, Gobolt पर देखें ):

Z4mainEUlRZ4mainE1TE_/7654536205164302515
Z4mainEUlRZ4mainE1TE0_/10614161759544824066






conditional-operator