स्पष्ट रूप से रिटर्न प्रकार बताते हुए लैम्बडा को कॉल अस्पष्ट है


11

एक अतिभारित फ़ंक्शन को दोनों फंक्शनलर्स को लेना चाहिए, यह देखते हुए कि लैम्ब्डा का प्रकार निर्णायक है (एक के लिए कास्टेबल है std::function(कृपया मुझे गलत होने पर सही करें)। सवाल यह है: लैम्ब्डा स्पष्ट रूप से होने के बावजूद नीचे एक संकलित त्रुटि क्यों है। परिभाषित। ( [&]() -> Type {})

कृपया ध्यान दें, कि मेरे वर्तमान समाधान के लिए मुझे कैप्चर-बाय-रेफरेंस की आवश्यकता है, यही कारण है कि कोड में इसके लिए तर्क हैं।

निम्नलिखित उदाहरण समस्या का वर्णन करता है:

#include <iostream>
#include <string>    
#include <functional>

void do_some(std::function<void(int)> thing) 
{
   thing(5);
}

void do_some(std::function<bool(int)> thing)
{
   if (thing(10)) 
   {
      std::cout << "it's true!" << std::endl;
   }
}

int main()
{
   int local_to_be_modified = 0;
   do_some(
      [&](int in)
      {
         local_to_be_modified = in;
         std::cout << "This is void-" << std::endl;
      }
   );
   do_some(
      [&](int in) -> bool
      { 
         // error: call to 'do_some' is ambiguous
         local_to_be_modified += in;
         std::cout << "This is bool-" << std::endl;
         return true;
      }
   );
}

6
क्योंकि std::function<void(int)>एक लैम्ब्डा से भी निर्माण किया जा सकता है जो कुछ लौटाता है (जिसके कारण वापसी मान को अनदेखा किया जाता है)।
होलीब्लैकैट

1
एक तरफ के रूप में, स्पष्ट रूप से उस मेमने के रिटर्न-प्रकार को निर्दिष्ट करना बिल्कुल कुछ नहीं करता है।
डेडुप्लिकेटर

जवाबों:


8

क्योंकि दूसरा लैम्ब्डा एक्सप्रेशन रिटर्निंग boolदोनों में बदल सकता है std::function<void(int)>और std::function<bool(int)>अंतर्निहित रूप से।

std::function एक परिवर्तित निर्माता है:

template< class F >
function( F f );

यह निर्माता अधिभार संकल्प में भाग नहीं लेता, जब तक कि च है प्रतिदेय तर्क प्रकारों args के लिए ... और वापसी प्रकार आर (के बाद से सी ++ 14)

कॉल करने योग्य की परिभाषा के रूप में ,

निम्नलिखित अभिव्यक्तियाँ मान्य होनी चाहिए:

INVOKE<R>(f, std::declval<ArgTypes>()...)

जहाँ INVOKE (f, t1, t2, ..., tN) को परिभाषित किया जाता है जैसे static_cast<void>(INVOKE(f, t1, t2, ..., tN))कि R संभवतः cv- क्वालिफाइड है void, अन्यथा INVOKE (f, t1, t2, ..., tN) , को संक्षेप में R में बदल दिया जाता है।

ध्यान दें कि , जैसा कि ऊपर दिखाया गया है, दूसरा लैम्ब्डा रिटर्निंग bool, एक वैध अभिव्यक्ति है (लौटाया गया बस कनवर्ट किया गया है )। तब यह स्पष्ट रूप से परिवर्तित हो सकता है और अस्पष्टता के मुद्दे का कारण बनता है।std::function<void(int)>static_cast<void>(INVOKE(f, t1, t2, ..., tN))boolvoidstd::function<void(int)>


6

आप स्पष्ट रूप static_castसे लंबोदर को उचित प्रकार से देख सकते हैं

using FunBoolRet = std::function<bool(int)>;

do_some(static_cast<FunBoolRet >([&](int in) 
   {
      local_to_be_modified += in;
      std::cout << "This is bool-" << std::endl;
      return true;
   }));

या मेमने को उचित std::function<bool(int)>प्रकार से स्टोर करें और फ़ंक्शन को पास करें (यदि do_some(lmda)कई बार कहा जाना चाहिए)

FunBoolRet lmda = [&](int in)
{
    local_to_be_modified += in;
    std::cout << "This is bool-" << std::endl;
    return true;
};    
do_some(lmda); // pass the lambda

या जैसा कि @MaxLanghof ने सुझाव दिया std::function<bool(int)>था कि जाने पर लैम्ब्डा से निर्माण करें

do_some(FunBoolRet{
   [&](int in) 
   {
      local_to_be_modified += in;
      std::cout << "This is bool-" << std::endl;
      return true;
   }
});

आप इसे छोड़ सकते हैं static_castऔर बस std::functionसीधे से इसका निर्माण कर सकते हैं । यह सब वैसे भी निहित रूपांतरण के दौरान होता है।
मैक्स लैंगहॉफ़

मेरा कहना है कि आप वस्तुतः सिर्फ static_cast<और सिर्फ हटा सकते हैं >और यह वही काम करेगा लेकिन कम टाइपिंग के साथ। इसके लिए अधिक लाइनों या किसी भी चीज की जरूरत नहीं है। godbolt.org/z/fQTqF4
मैक्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.