2010-09-28 10 views
32

टेम्पलेट पैरामीटर के रूप में लैम्ब्डा अभिव्यक्ति का उपयोग कैसे करें? जैसे एक एसडीडी :: सेट शुरू करने के लिए एक तुलना वर्ग के रूप में।टेम्पलेट पैरामीटर के रूप में लैम्ब्डा अभिव्यक्ति का उपयोग कैसे करें?

निम्नलिखित समाधान काम करना चाहिए, क्योंकि लैम्ब्डा अभिव्यक्ति केवल एक अज्ञात संरचना बनाता है, जो टेम्पलेट पैरामीटर के रूप में उपयुक्त होना चाहिए। हालांकि, बहुत सारी त्रुटियां पैदा हुई हैं।

कोड उदाहरण:

struct A {int x; int y;}; 
std::set <A, [](const A lhs, const A &rhs) ->bool { 
    return lhs.x < rhs.x; 
    } > SetOfA; 

त्रुटि निर्गम (मैं जी ++ 4.5.1 संकलक और --std = C++ 0x संकलन ध्वज का उपयोग कर रहा):

error: ‘lhs’ cannot appear in a constant-expression 
error: ‘.’ cannot appear in a constant-expression 
error: ‘rhs’ cannot appear in a constant-expression 
error: ‘.’ cannot appear in a constant-expression 
At global scope: 
error: template argument 2 is invalid 

है कि अपेक्षित व्यवहार या जीसीसी में एक बग?

संपादित

के रूप में किसी को, मैं गलत तरीके से के रूप में वे गुमनाम struct वे बात कर रहे हैं की एक उदाहरण लौट लैम्ब्डा भाव उपयोग कर रहा हूँ ने कहा।

हालांकि, उस त्रुटि को ठीक करने से समस्या हल नहीं होती है। मैं निम्नलिखित कोड के लिए lambda-expression in unevaluated context त्रुटि मिलती है:

struct A {int x; int y;}; 
typedef decltype ([](const A lhs, const A &rhs) ->bool { 
    return lhs.x < rhs.x; 
    }) Comp; 
std::set <A, Comp > SetOfA; 
+1

मैं इस टैग किया सी ++ 0x के रूप में। यह अधिक उपयुक्त लगता है और बेहतर जवाब मिलना चाहिए। – JoshD

+1

@JoshD क्या इसे अभी भी 'C++' टैग नहीं किया जाना चाहिए? 0x अंततः नया मानक बनने जा रहा है और मैं नहीं चाहता कि भविष्य में लोगों को इस प्रश्न को याद किया जाए क्योंकि वे भूल गए थे कि उचित टैग सी ++ 0x सी ++ नहीं था। (या फिर कुछ सी ++ 0x टैग को किसी बिंदु पर सी ++ में माइग्रेट करने जा रहा है?) – KitsuneYMG

उत्तर

33

std::set के 2 टेम्पलेट पैरामीटर एक प्रकार, न कि एक अभिव्यक्ति उम्मीद है, तो यह सिर्फ आप इसे गलत तरीके से उपयोग कर रहे हैं।

आप इस तरह सेट बनाने सकता है: अगर यह तुम क्या पूछ रहे हैं है

auto comp = [](const A& lhs, const A& rhs) -> bool { return lhs.x < rhs.x; }; 
auto SetOfA = std::set <A, decltype(comp)> (comp); 
+0

लैम्ब्डा अभिव्यक्ति वास्तव में एक प्रकार है। परिभाषित ऑपरेटर() के साथ एक अज्ञात संरचना घोषित करने का यह एक और तरीका है। मैं प्रकार के विनिर्देशक के रूप में लैम्ब्डा का उपयोग नहीं करता हूं: std :: ser <, ....> बी –

+11

@ बबेटिना: यदि यह * एक प्रकार था तो '[]() {} x;' वैध घोषणा होनी चाहिए । लैम्ब्डा अभिव्यक्ति उस अज्ञात संरचना का सिर्फ एक * उदाहरण * है। उस प्रकार को पाने के लिए आपको 'decltype' की आवश्यकता है। – kennytm

+0

ठीक है, अब इसे साफ़ कर दिया गया है :) लेकिन decltype भी किसी भी तरह काम नहीं करता –

1

सुनिश्चित नहीं हैं, लेकिन एक लैम्ब्डा जो RetType वापस आती है और स्वीकार करता है के हस्ताक्षर InType हो जाएगा:

std::function<RetType(InType)> 
(ला के बाद से (सुनिश्चित करें कि #include <functional> को बनाओ)

आप छोटा कर सकते हैं कि एक typedef का उपयोग करके, लेकिन मैं नहीं सुनिश्चित करें कि आप decltype का उपयोग वास्तविक प्रकार पता लगाना से बचने के लिए कर सकते हैं जाहिरा तौर पर mbdas कि इस संदर्भ में प्रयोग किया जाता है नहीं किया जा सकता)

तो अपने typedef किया जाना चाहिए:।

typedef std::function<bool(const A &lhs, const A &rhs)> Comp 

या

using Comp = std::function<bool(const A &lhs, const A &rhs)>; 
+0

+1 क्योंकि यह समाधान है, लेकिन 'std :: function' सिर्फ एक धारक प्रकार है। आप * लैम्ब्डा को 'फ़ंक्शन' में परिवर्तित कर सकते हैं और लैम्बडा को ऑब्जेक्ट * पॉइंटिंग * प्राप्त कर सकते हैं, लेकिन यह इसका मूल प्रकार नहीं है। – Potatoswatter

+0

संपादित करें: फ़ंक्शन लैम्ब्डा को इंगित नहीं करता है, इसमें यह शामिल है। लेकिन वैसे भी यह मूल प्रकार नहीं था। – Potatoswatter

+0

आह, जानना अच्छा है। मैं इसे इनलाइन-लैम्ब्डा सिंटैक्स लेता हूं कुछ यादृच्छिक रूप से जेनरेट किए गए प्रकार का उत्पादन करता है ताकि कोई भी बिल्कुल समान न हो? (इस प्रकार सी # यह करता है, आईआईआरसी।) –

4

इस रास्ते का इस्तेमाल किया तुलनाकारक, आप अब भी साथ बेहतर कर रहे हैं एक गैर 0x दृष्टिकोण:

struct A { int x; int y; }; 

struct cmp_by_x { 
    bool operator()(A const &a, A const &b) { 
    return a.x < b.x; 
    } 
}; 

std::set<A, cmp_by_x> set_of_a; 

हालांकि, 0x से आप cmp_by_x एक स्थानीय प्रकार कर सकते हैं (यानी इसे किसी फ़ंक्शन के अंदर परिभाषित करें) जब यह अधिक सुविधाजनक होता है, जिसे वर्तमान C++ द्वारा प्रतिबंधित किया जाता है।

इसके अलावा, आपकी तुलना ए (x = 1, y = 1) और ए (x = 1, y = 2) समकक्ष के रूप में व्यवहार करती है।यदि यह वांछित नहीं है, तो आप अन्य मूल्यों कि विशिष्टता करने के लिए योगदान शामिल करने की जरूरत:

struct cmp_by_x { 
    bool operator()(A const &a, A const &b) { 
    return a.x < b.x || (a.x == b.x && a.y < b.y); 
    } 
}; 
0

समस्या पिछले टेम्पलेट पैरामीटर है, टाइप नहीं एक वस्तु तो आप क्या करना चाहते हो सकता है निम्न

std::set <A, std::fuction<bool(const A &,const A &)>> 
       SetOfA([](const A lhs, const A &rhs) ->bool { 
                  return lhs.x < rhs.x; 
                  } > SetOfA; 

यह सरल आप कर सकते हैं बनाने के लिए निम्नलिखित:

auto func = SetOfA([](const A lhs, const A &rhs) ->bool { return lhs.x < rhs.x;} 
set <A,decltype(func)> SetOfA(func); 

चियर्स

संबंधित मुद्दे