सामान्य लैंबडा C ++ 14 में कैसे काम करता है?


114

जेनेरिक लैम्ब्डा कैसे काम करता है (autoC ++ 14 मानक में एक तर्क प्रकार के रूप में कीवर्ड)?

क्या यह C ++ टेम्प्लेट पर आधारित है जहां प्रत्येक अलग-अलग तर्क प्रकार के कंपाइलर एक ही बॉडी के साथ एक नया फंक्शन उत्पन्न करते हैं लेकिन बदले हुए प्रकार (कंपाइल-टाइम पॉलीमॉर्फिज्म) या यह जावा के जेनेरिक्स (टाइप इरेज़र) के समान है?

कोड उदाहरण:

auto glambda = [](auto a) { return a; };

6
सी ++ से 14 फिक्स्ड, मूल रूप से प्रश्न में प्रयोग किया जाता सी ++ 11
sasha.sochka

जवाबों:


130

जेनेरिक लैंबडस को पेश किया गया था C++14

सीधे शब्दों में, बंद प्रकार लैम्ब्डा अभिव्यक्ति द्वारा परिभाषित एक होगा टेम्प्लेट की गई कॉल ऑपरेटर के बजाय नियमित रूप से, गैर टेम्पलेट कॉल ऑपरेटर C++11के lambdas (बेशक, जब autoप्रकट होता है कम से कम पैरामीटर सूची में एक बार)।

तो आपका उदाहरण:

auto glambda = [] (auto a) { return a; };

glambdaइस प्रकार का उदाहरण देंगे :

class /* unnamed */
{
public:
    template<typename T>
    T operator () (T a) const { return a; }
};

C ++ 14 स्टैंडर्ड ड्राफ्ट n3690 का पैरा 5.1.2 / 5 निर्दिष्ट करता है कि किसी दिए गए लैम्ब्डा अभिव्यक्ति के क्लोजर प्रकार के कॉल ऑपरेटर को कैसे परिभाषित किया गया है:

गैर-जेनेरिक लैम्ब्डा-अभिव्यक्ति के लिए क्लोजर प्रकार में एक सार्वजनिक इनलाइन फ़ंक्शन कॉल ऑपरेटर (13.5.4) होता है, जिसके पैरामीटर और रिटर्न प्रकार क्रमशः लैम्ब्डा-एक्सप्रेशन के पैरामीटर-घोषणा-खंड और ट्रेलिंग-रिटर्न-टाइप प्रकार द्वारा वर्णित किए जाते हैं। एक सामान्य लैम्ब्डा के लिए, क्लोजर प्रकार में एक सार्वजनिक इनलाइन फ़ंक्शन कॉल ऑपरेटर सदस्य टेम्पलेट (14.5.2) होता है, जिसका टेम्प्लेट-पैरामीटर-लिस्ट में लैम्बडा के पैरामीटर-डिक्लेरेशन-क्लॉज में ऑटो की प्रत्येक घटना के लिए एक आविष्कार किए गए टाइप-टेम्प्लेट-पैरामीटर होते हैं, प्रकटन के क्रम में। इन्वेंटेड टाइप टेम्प्लेट-पैरामीटर एक पैरामीटर पैक है, यदि संबंधित पैरामीटर-डिक्लेरेशन फ़ंक्शन पैरामीटर पैक (8.3.5) घोषित करता है। फ़ंक्शन कॉल ऑपरेटर टेम्पलेट का रिटर्न प्रकार और फ़ंक्शन पैरामीटर लंबर-एक्सप्रेशन-ट्रेलिंग-रिटर्न-टाइप और पैरामीटर-डिक्लेरेशनक्लॉज से उत्पन्न होते हैं, जो पैरामीटर-घोषणा-क्लॉज के घोषित-निर्दिष्टकों में ऑटो के प्रत्येक घटना को नाम के साथ प्रतिस्थापित करके होता है। इसी आविष्कार किए गए टेम्प्लेट-पैरामीटर।

आखिरकार:

क्या यह उन टेम्पलेट्स के समान है जहां प्रत्येक भिन्न तर्क प्रकार के कंपाइलर एक ही बॉडी के साथ कार्य करते हैं लेकिन बदले हुए प्रकार या यह जावा के जेनेरिक के समान है?

जैसा कि ऊपर पैराग्राफ में बताया गया है, जेनेरिक लैंबडास एक टेम्प्लेटेड कॉल ऑपरेटर के साथ अनूठे, अनाम फंक्शनल के लिए सिंटैक्टिक शुगर है। कि आपके सवाल का जवाब देना चाहिए :)


7
हालाँकि, वे टेम्पलेट पद्धति से स्थानीय रूप से परिभाषित वर्ग की भी अनुमति देते हैं। जो नया है।
याक - एडम नेवरामोंट

2
@ याक: पहले से ही C ++ 11 के साथ फंक्शन-लोकल टेम्प्लेट के लिए प्रतिबंध पूरी तरह से नहीं गिरा था?
सेबस्टियन मच

2
@phresnel: नहींं, वह प्रतिबंध नहीं हटाया गया है
एंडी प्रोल

1
@AndyProwl: मुझे अपनी गलती का एहसास है। क्या उठाया गया था वास्तव में टेम्पलेट तर्क के रूप में स्थानीय प्रकार का उपयोग कर रहा था (में int main () { struct X {}; std::vector<X> x; })
सेबस्टियन मच

1
@phresnel: सही है, कि वास्तव में बदल गया है
एंडी प्रोल

25

दुर्भाग्य से , वे C ++ 11 ( http://ideone.com/NsqYuq ) का हिस्सा नहीं हैं :

auto glambda = [](auto a) { return a; };

int main() {}

जी ++ 4.7 के साथ:

prog.cpp:1:24: error: parameter declared auto
...

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

[](const& x, & y){ return x + y; }

यह सबसे बड़ा हिस्सा एक सामान्य फ़नकार वर्ग के सामान्य निर्माण के लिए निकलेगा, लेकिन प्रकारों की कमी के साथ कंपाइलर एक अस्थायी सदस्य को बाहर कर देगा- operator():

struct anonymous
{
    template <typename T, typename U>
    auto operator()(T const& x, U& y) const -> decltype(x+y)
    { return x + y; }
};

या नए प्रस्ताव के अनुसार जेनेरिक (पॉलीमॉर्फिक) लैम्ब्डा एक्सप्रेशंस के लिए प्रस्ताव

auto L = [](const auto& x, auto& y){ return x + y; };

--->

struct /* anonymous */
{
    template <typename T, typename U>
    auto operator()(const T& x, U& y) const // N3386 Return type deduction
    { return x + y; }
} L;

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


6
उस प्रकार-विशेष को छोड़ने की अनुमति देने का प्रस्ताव बिलकुल घटिया है।
लाइटवेट रेस ऑर्बिट में

वे g ++ - 4.9 के साथ गए । आपको आपूर्ति करने की आवश्यकता है -std=c++1y
ईम्र

मुझे महसूस नहीं हुआ कि आइडोन में अभी gcc-4.9 और C ++ 14 नहीं है।
एम्स

प्रश्न: क्या autoइसमें क्लासिक ऑटो की तुलना में समान कटौती नियम हैं? यदि हम टेम्प्लेटेड सादृश्य का उल्लेख करते हैं, तो इसका मतलब होगा कि ऑटो ऑटो नहीं है, यह उसी प्रकार का नियम है जैसे टेम्पलेट प्रकार की कटौती। फिर सवाल यह है: क्या टेम्पलेट कटौती के बराबर है auto?
v.oddou

@ v.oddou: "क्लासिक ऑटो" अच्छा है। मेरे लिए, "क्लासिक ऑटो" का अर्थ है "स्टैक वेरिएबल", और एक बार इसके विपरीत staticया register:) वैसे भी उपयोग किया जाता था , हाँ, autoवहाँ का उपयोग करने का मतलब है कि हुड के तहत, एक सामान्य टेम्पलेट उत्पन्न होता है। वास्तव में, एक लैम्ब्डा को कंपाइलर-आंतरिक रूप से एक फ़नकार वर्ग द्वारा प्रतिस्थापित किया जाएगा, और एक autoपैरामीटर का मतलब है कि template <T> ... (T ...)उत्सर्जित किया जाएगा।
सेबस्टियन मच

17

यह एक प्रस्तावित C ++ 14 फीचर है (C ++ 11 में नहीं) समान (या समतुल्य) टेम्पलेट्स के लिए। उदाहरण के लिए, N3559 यह उदाहरण प्रदान करता है:

उदाहरण के लिए, इस सामान्य लंबोदर-अभिव्यक्ति वाले कथन:

auto L = [](const auto& x, auto& y){ return x + y; };

एक क्लोजर प्रकार के निर्माण में परिणाम हो सकता है, और ऑब्जेक्ट जो नीचे की संरचना के समान व्यवहार करता है:

struct /* anonymous */
{
    template <typename T, typename U>
    auto operator()(const T& x, U& y) const // N3386 Return type deduction
    { return x + y; }
} L;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.