क्या लैम्ब्डा कार्यों को समाप्त किया जा सकता है?


230

C ++ 11 में, लैम्ब्डा फ़ंक्शन को टेम्प्लेट करने का एक तरीका है? या क्या यह स्वाभाविक रूप से टेम्पर्ड होने के लिए बहुत विशिष्ट है?

मैं समझता हूं कि मैं इसके बजाय एक क्लासिक टेंपलेटेड क्लास / फ़नकार को परिभाषित कर सकता हूं, लेकिन यह सवाल अधिक है: क्या भाषा टेम्परिंग लैम्ब्डा कार्यों की अनुमति देती है?


क्या कोई उपयोग मामला है जहां एक लैम्ब्डा टेम्पलेट उपयोगी होगा?
जेम्स मैकनेलिस

7
जेम्स: आप एक समारोह का निर्माण कर सकते हैं एक टपल पर पुनरावृति करने के लिए (जरूरी नहीं कि उपयोगी हो)।
जो डी

मैं विचार के बारे में सोचा था जब एक समस्या के रूप में मेटा-टेम्प्लेट जटिलता के बारे में बात करते हुए स्ट्रॉस्ट्रुप का एक साक्षात्कार पढ़ा। यदि यह अनुमति दी गई थी, तो मैं निंजा कोड-फू की कल्पना कर रहा था जो कि इस फीचर संयोजन के साथ खेलने वाले बहुत ही चतुर प्रोग्रामर द्वारा आविष्कार किया जा सकता है ...
क्लेम २६'१०

जवाबों:


181

UPDATE 2018: C ++ 20 टेम्प्लेटेड और कॉन्सेप्टिव लैम्ब्डा के साथ आएगा। सुविधा को पहले ही मानक मसौदे में एकीकृत कर दिया गया है।


अद्यतन 2014: C ++ 14 को इस वर्ष जारी किया गया है और अब इस उदाहरण में उसी वाक्य रचना के साथ पॉलीमॉर्फिक लैम्ब्डा प्रदान करता है। कुछ प्रमुख कंपाइलर इसे पहले ही लागू कर देते हैं।


यह खड़ा है (C ++ 11 में), दुख की बात है कि नहीं। लचीलेपन और शक्ति के मामले में बहुरूपी लंबोदर उत्कृष्ट होंगे।

मूल कारण वे मोनोमोर्फिक होने के कारण अवधारणाओं के कारण समाप्त हो गए। अवधारणाओं ने इस कोड की स्थिति को मुश्किल बना दिया:

template <Constraint T>
void foo(T x)
{
    auto bar = [](auto x){}; // imaginary syntax
}

एक संकुचित टेम्पलेट में आप केवल अन्य विवश टेम्पलेट को कॉल कर सकते हैं। (अन्यथा बाधाओं की जाँच नहीं की जा सकी।) fooआह्वान किया जा सकता है bar(x)? लैम्ब्डा में क्या अड़चनें हैं (इसके लिए पैरामीटर सिर्फ एक टेम्पलेट है, आखिर)?

इस तरह की चीजों से निपटने के लिए अवधारणाएं तैयार नहीं थीं; इसके लिए और अधिक सामान की आवश्यकता होगी late_check(जहाँ अवधारणा को लागू होने तक जाँच नहीं किया गया था) और सामान। सरल यह सब गिराने और मोनोमोर्फिक लैम्ब्डा से चिपके रहने के लिए था।

हालांकि, C ++ 0x से अवधारणाओं को हटाने के साथ, बहुरूपी लैम्ब्डा फिर से एक सरल प्रस्ताव बन जाता है। हालाँकि, मुझे इसके लिए कोई प्रस्ताव नहीं मिला। :(


5
सरल ... सिवाय अवधारणाओं को फिर से प्रस्तुत करने और उन्हें जटिल बनाने वाली विशेषताओं से बचने की इच्छा के अलावा।

6
मुझे लगता है कि मेरे पास अवधारणाओं की तुलना में बहुरूपता वाले लंबोदर होंगे। मुझे समझ नहीं आया कि उदाहरण किसी भी चीज को कैसे प्रेरित करता है; आप इसे एक त्रुटि के रूप में मना कर सकते हैं, और लैंबडा को मोनोमोर्फिक [] (T x) {} या एक विवश टेम्पलेट [] टेम्पलेट <constraint T> (T x) {} की आवश्यकता होगी, जिसे मिलान के लिए वैधानिक रूप से सत्यापित किया जा सकता है। क्या कोई कारण है कि यह संभव नहीं था?
DrPizza

13
आपको अवधारणाओं और बहुरूपताओं के बीच चयन करने की ज़रूरत नहीं है: cpp-next.com/archive/2011/12/a-breakthrough-for-concepts
डेव अब्राहम

3
यहाँ पॉलिमॉर्फिक लैम्ब्डा का प्रस्ताव है: open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3418.pdf और क्लैंग में टॉय कार्यान्वयन: faisalv.github.com/clang-glambda
Radif Sharafullin

18
पॉलिमॉर्फिक लैम्ब्डा C ++ 14 में होगा, कम से कम अब तक वे सामुदायिक ड्राफ्ट में हैं :)
Arne Mertz

37

C ++ 11 लैम्ब्डा को अन्य उत्तरों में बताए अनुसार नहीं निकाला जा सकता है, लेकिन decltype()टेम्पर्ड क्लास या फ़ंक्शन के भीतर लैम्ब्डा का उपयोग करते समय मदद करता है।

#include <iostream>
#include <string>

using namespace std;

template<typename T>
void boring_template_fn(T t){
    auto identity = [](decltype(t) t){ return t;};
    std::cout << identity(t) << std::endl;
}

int main(int argc, char *argv[]) {
    std::string s("My string");
    boring_template_fn(s);
    boring_template_fn(1024);
    boring_template_fn(true);
}

प्रिंटों:

My string
1024
1

मैंने पाया है कि यह तकनीक टेम्पर्ड कोड के साथ काम करने में मदद करती है, लेकिन यह महसूस करती है कि अभी भी इसका मतलब है कि लैम्ब्डा खुद को टेम्पलेटेड नहीं किया जा सकता है।


26
Tdecltype(t)इस उदाहरण के स्थान पर ठीक काम करेगा ।
2020 बजे user2023370

26

सी ++ 11 में, लैम्ब्डा कार्यों को टेंपलेट नहीं किया जा सकता है, लेकिन आईएसओ सी ++ मानक के अगले संस्करण में (जिसे अक्सर सी ++ 14 कहा जाता है), यह सुविधा पेश की जाएगी। [स्रोत]

उपयोग उदाहरण:

auto get_container_size = [] (auto container) { return container.size(); };

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


5
autoप्रकार कटौती के नियमों को विशेष रूप से templateफ़ंक्शन तर्क कटौती के समान ही परिभाषित किया गया है ।
अंडरस्कोर_ड

10

मुझे पता है कि यह सवाल C ++ 11 के बारे में है। हालाँकि, इस पेज पर जाने और उतरने वालों के लिए, टेम्पर्ड लैम्ब्डा को अब C ++ 14 में सपोर्ट किया गया है और जेनेरिक लैम्ब्डा नाम से जाना जाता है।

[जानकारी] अधिकांश लोकप्रिय संकलक अब इस सुविधा का समर्थन करते हैं। Microsoft Visual Studio 2015 का समर्थन करता है। दबंग समर्थन करते हैं। जीसीसी सपोर्ट करता है।


6

मुझे आश्चर्य है कि इस बारे में:

template <class something>
inline std::function<void()> templateLamda() {
  return [](){ std::cout << something.memberfunc() };
}

मैंने एक टेम्पलेट उत्पन्न करने के लिए इसी तरह के कोड का उपयोग किया और आश्चर्य किया कि क्या कंपाइलर "रैपिंग" फ़ंक्शन को बाहर कर देगा।


2
क्या संकलक? ने करदी?
NicoBerrogorry

4

पॉलीमोर्फिक लैम्ब्डा के लिए Boost.Phoenix पर एक नज़र डालें: http://www.boost.org/doc/libs/1_44_0/libs/spirit/phoenix/doc/html/indexx " C ++ 0x की आवश्यकता नहीं है, द्वारा मार्ग :)


2
मैं पहले से ही इसके बारे में जानता हूं, लेकिन सवाल वैसे भी नए मानक के बारे में है;)
9

ठीक है :) सी ++ 0x लैम्ब्डा मोनोमोर्फिक हैं और दुर्भाग्य से, इसे विस्थापित नहीं किया जा सकता है।
usta

3

एक gcc एक्सटेंशन है जो लैम्ब्डा टेम्प्लेट की अनुमति देता है :

// create the widgets and set the label
base::for_each(_widgets, [] <typename Key_T, typename Widget_T>
                         (boost::fusion::pair<Key_T, Widget_T*>& pair) -> void {
                             pair.second = new Widget_T();
                             pair.second->set_label_str(Key_T::label);
                          }
              );

कहां _widgetsहैstd::tuple< fusion::pair<Key_T, Widget_T>... >


एफडब्ल्यूआईडब्ल्यू, यह सी ++ 20 में मानक वाक्यविन्यास बन गया है।
एलएफ

2

मैं ध्वज के version 5.0.1साथ संकलित नवीनतम क्लैंग के साथ खेल रहा हूं -std=c++17और अब लैम्बदास के लिए ऑटो टाइप मापदंडों के लिए कुछ अच्छा समर्थन है:

#include <iostream>
#include <vector>
#include <stdexcept>

int main() {
    auto slice = [](auto input, int beg, int end) {
        using T = decltype(input);
        const auto size = input.size();
        if (beg > size || end > size || beg < 0 || end < 0) {
            throw std::out_of_range("beg/end must be between [0, input.size())");
        }
        if (beg > end) {
            throw std::invalid_argument("beg must be less than end");
        }
        return T(input.begin() + beg, input.begin() + end);
    };
    auto v = std::vector<int> { 1,2,3,4,5 };
    for (auto e : slice(v, 1, 4)) {
        std::cout << e << " ";
    }
    std::cout << std::endl;
}

1

यहां एक समाधान है जिसमें एक संरचना में लांबा को लपेटना शामिल है:

template <typename T>                                                   
struct LamT                                                             
{                                                                       
   static void Go()                                                     
   {                                                                    
      auto lam = []()                                                   
      {                                                                 
         T var;                                                         
         std::cout << "lam, type = " << typeid(var).name() << std::endl;
      };                                                                

      lam();                                                            
   }                                                                    
};   

उपयोग करने के लिए:

LamT<int>::Go();  
LamT<char>::Go(); 
#This prints 
lam, type = i
lam, type = c

इसके साथ मुख्य मुद्दा (अतिरिक्त टाइपिंग के अलावा) आप इस संरचना की परिभाषा को किसी अन्य विधि के अंदर एम्बेड नहीं कर सकते हैं या आपको मिल सकता है (gcc 4.9)

error: a template declaration cannot appear at block scope

मैंने भी ऐसा करने की कोशिश की:

template <typename T> using LamdaT = decltype(                          
   [](void)                                                          
   {                                                                 
       std::cout << "LambT type = " << typeid(T).name() << std::endl;  
   });

इस आशा के साथ कि मैं इसका इस तरह उपयोग कर सकता हूं:

LamdaT<int>();      
LamdaT<char>();

लेकिन मुझे संकलक त्रुटि मिलती है:

error: lambda-expression in unevaluated context

तो यह काम नहीं करता है ... लेकिन अगर यह संकलित करता है, तो यह सीमित उपयोग का होगा क्योंकि हमें अभी भी फाइल स्कोप पर "लैमडाट का उपयोग करना" पड़ेगा (क्योंकि यह एक टेम्प्लेट है) जो इस तरह के उद्देश्य को हरा देता है lambdas।


1

मुझे यकीन नहीं है कि किसी और ने यह सुझाव क्यों नहीं दिया है, लेकिन आप एक टेम्पर्ड फ़ंक्शन लिख सकते हैं जो लैम्ब्डा फ़ंक्शन देता है। निम्नलिखित ने मेरी समस्या को हल किया, इस पृष्ठ पर आने का कारण:

template <typename DATUM>
std::function<double(DATUM)> makeUnweighted() {
  return [](DATUM datum){return 1.0;};
}

अब जब भी मुझे कोई ऐसा फ़ंक्शन चाहिए, जो किसी प्रकार का तर्क देता हो (उदाहरण के लिए std::string), तो मैं कहता हूँ

auto f = makeUnweighted<std::string>()

और अब f("any string")लौटता है 1.0

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


2
यह केवल तभी काम करता है जब आप लैम्ब्डा बनाने से पहले लैम्ब्डा के लिए तर्क के प्रकार को जानते हैं, जिस स्थिति में आप लॉम्ब को केवल विशिष्ट प्रकार के तर्क के रूप में उपयोग कर सकते हैं। पॉलीमॉर्फिक लैम्ब्डा का उद्देश्य एक तर्क प्रकार पर काम करने के लिए प्रदान करना है जिसे आप कभी नहीं जानते हैं कि आप कार्य कोड कब लिखते हैं। मूल रूप से, यह पूरी तरह से अलग है, यही वजह है कि इसका सुझाव नहीं दिया गया था।
22

आह, ठीक है, समझ गया। मैं उस उपयोग के मामले के बारे में नहीं सोचता था --- मुझे लगता है कि लैम्ब्डा फंक्शन ऑन-द-फ्लाई चीजें और उस तरह के बहुरूपता के रूप में एक बहुउद्देशीय पुस्तकालय में कुछ है। मैं एक टेम्प्लेटेड लाइब्रेरी लिख रहा था जिसे किसी भी प्रकार के उपयोगकर्ता के लंबो कार्यों को स्वीकार करने की आवश्यकता है और सही प्रकार की चूक भी प्रदान करता है।
जिम पीवार्स्की
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.