2010-02-07 14 views
6

मुझे हास्केल स्टाइल पैटर्न मिलान पसंद है। वहाँ किसी मैक्रो मैं इस सरल करने के लिए परिभाषित करते हैं कर सकते हैंसी ++ में पैटर्न मिलान शैली?

ObjectPtr ptr; 
if(ptr.isType<Foo>()) { // isType returns a bool 
    Ptr<Foo> p = ptr.convertAs<Foo>(); // convertAs returns a Ptr<Foo> 
    ...... 
} 
if(ptr.isType<Bar>()) { 
    Ptr<Bar> p = ptr.convertAs<Bar>(); 
    ...... 
} 

अब,:

मैं इस प्रकार मेरी सी ++ कोड है? मैं थोड़ी देर के लिए इस पर विचार कर रहा हूं, लेकिन इसे और सरल नहीं कर सकता।

धन्यवाद!

+2

मुझे लगता है कि आप 'isType' के बाद'() 'गायब हैं। – AndiDog

+0

अच्छी कॉल। टिप्पणी पर +1। – anon

+0

Mach7 में, अपने कोड निम्नलिखित के रूप में दिखेगा:

 Match(*ptr) { Case(Foo) return match0.foo_member(); Case(Bar) return match0.bar_member(); Otherwise() return 0; } EndMatch 
https://github.com/solodon4/Mach7 और प्रयास के लिए – solodon

उत्तर

2

मैं यह सोचते हैं रहा हूँ अपने Ptr टेम्पलेट एक शून्य सूचक की अवधारणा है।

ObjectPtr ptr; 
if(Ptr<Foo> p = ptr.convertAs<Foo>()) { // convertAs returns a NULL pointer if the conversion can't be done. 
    ...... 
} 
if(Ptr<Bar> p = ptr.convertAs<Bar>()) { 
    ...... 
} 

हालांकि, जैसा कि अन्य ने ध्यान दिया है, प्रकार पर स्विचिंग आमतौर पर एक संकेत है कि आप सी ++ में कुछ गलत कर रहे हैं। आपको इसके बजाय आभासी कार्यों का उपयोग करने पर विचार करना चाहिए।

+0

क्या यह सिर्फ एक और सवाल उठाता है - "मैं इसे बदलने के लिए कन्वर्टएस() कैसे लिखूं?" –

+0

@Neil: वास्तव में नहीं - उसका मूल कोड एक कन्वर्टएस के अस्तित्व को ग्रहण करता है। यह संभावित रूप से एक गतिशील_कास्ट का उपयोग करेगा, जो एक शून्य सूचक उत्पन्न करता है अगर यह एक सूचक को लक्ष्य प्रकार में परिवर्तित नहीं कर सकता है। इस प्रकार, संभावनाएं बहुत अच्छी हैं कि यह पहले से मौजूद है, या उपस्थित होने पर लागू करने में काफी आसान है। –

+2

सबसे अच्छा हिस्सा है, सी ++ 0x में आप 'ऑटो' के साथ 'Ptr 'को प्रतिस्थापित कर सकते हैं। – Omnifarious

7

dynamic_cast क्या आप

struct A { 
    virtual ~A() {} 
}; 

struct B : struct A { ... }; 
struct C : struct A { ... }; 

A * a = new C; 

if (C * c = dynamic_cast<C*>(a)) { 
    c->someCfunc(); 
} 
else if (B * b = dynamic_cast<B*>(a)) { 
    b->someBfunc(); 
} 
else { 
    throw "Don't know that type"; 
} 
+0

+1 नीचे Mach7 के बारे में मेरा उत्तर देखें। हालांकि, मैं स्मार्ट पॉइंटर्स का उपयोग कर रहा हूं। – anon

+0

फिर निहित पॉइंटर पर गतिशील कास्ट करें - उदाहरण के लिए, यदि आप std :: auto_ptr() का उपयोग कर रहे हैं, तो इसे प्राप्त करने के परिणाम पर प्राप्त करें()। –

7

चाहते मैं प्यार करता हूँ हास्केल शैली पैटर्न मिलान करने के लिए दिखाई देता है।

फिर अपना प्रोग्राम हास्केल में लिखें।

आप जो करने का प्रयास कर रहे हैं वह एक प्रकार पर स्विच है। अगर वे वर्चुअल फ़ंक्शंस से बचना चाहते हैं तो यह एक आम बात है। अब, उत्तरार्द्ध सी ++ में ओओ के बारे में एक आधारशिला है। यदि आप उनसे बचना चाहते हैं, तो आप सी ++ में प्रोग्राम क्यों करते हैं?


क्यों इस पर सिकोड़ी है के लिए के रूप में: कल्पना कीजिए कि आप इस

if(ptr.isType<Foo>()) ... 
if(ptr.isType<Bar>()) ... 

अपने कोड भर में लिप्त की तरह कोड का एक बहुत कुछ है और फिर किसी आता है और संभव प्रकार के Baz कहते हैं कि हो सकता है ptr प्रतिनिधित्व करते हैं। अब आप एक बड़े कोड बेस के माध्यम से शिकार कर रहे हैं, उन सभी स्थानों को खोजने का प्रयास कर रहे हैं जहां आपने एक प्रकार से स्विच किया था, और यह पता लगाने की कोशिश कर रहे हैं कि आपको Baz को जोड़ने की आवश्यकता है।

और, जैसा कि मर्फी के पास है, बस जब आपका काम होता है, तो Foz के साथ भी एक प्रकार के रूप में जोड़ा जा सकता है। (या, फिर से सोच, यह ढोंगी अगर मर्फी अपने तरीका है में इससे पहले कि आप Baz जोड़ने भी पूरा मौका मिला।)

+2

स्टैक पर ऑब्जेक्ट्स के सी कन्स्ट्रक्टर्स और डिस्ट्रक्टरों का निम्न स्तर मेमोरी कंट्रोल <- यह आश्चर्यजनक है, क्योंकि यह स्मार्ट पॉइंटर्स, आरएआईआई, ... देता है; मानक टेम्पलेट पुस्तकालय (क्या इनमें से कोई वर्चुअल फ़ंक्शन का उपयोग करता है?)। +1 मानते हुए जवाब असली सवाल था, ट्रोल नहीं। – anon

+1

यह निश्चित रूप से एक वास्तविक सवाल नहीं था, लेकिन न ही यह एक ट्रोल था। यह एक अशिष्ट सवाल था। सादा होने के लिए: _ आपको इसे C++ _ में नहीं करना चाहिए। यही वर्चुअल फ़ंक्शंस का आविष्कार किया गया था; उन्होंने 'फू' प्रकार की वस्तुओं से संबंधित सभी कोड 'फू' में, और 'बाज़' से संबंधित' बज़ 'से संबंधित सभी कोड डाल दिए।यह हमेशा सबसे अच्छा नहीं है जिसे आप प्राप्त कर सकते हैं (गवाह, उदाहरण के लिए, विज़िटर पैटर्न के पीछे प्रेरणा), लेकिन यह डिफ़ॉल्ट है जिसे आपको सी ++ में शुरू करना चाहिए। – sbi

+0

'अब, उत्तरार्द्ध सी ++ में ओओ के बारे में एक आधारशिला है। 'फिर हमें टेम्पलेट मेटाप्रोग्रामिंग का उपयोग क्यों करना चाहिए जब यह मूल रूप से एफपी है और ओओ नहीं है, हमें सभी को एसटीएल का उपयोग करने के बजाय हास्केल जाना चाहिए, अपने स्वयं के टेम्पलेट्स को बढ़ावा देना या उपयोग करना ... _rolleyes_ इसके अलावा सी ++ की पूरी तरह से अज्ञानी कोई ऐसा सवाल करेगा, [इस आदमी की तरह (पीडीएफ से लिंक)] (http://www.stroustrup.com/OpenPatternMatching.pdf) पूरी तरह से जानकारी नहीं! – Trinidad

2

एक लगता है कि यह मैक्रो ठीक करता है कि आप क्या चाहते:

#define DYN_IF(dest_type, dest_ptr, src_ptr)         \ 
    if((src_ptr).isType<dest_type>())          \ 
     if(int dest_type##dest_ptr = 1)          \ 
     for(Ptr<dest_type> dest_ptr = (src_ptr).convertAs<dest_type>();  \ 
      dest_type##dest_ptr;            \ 
      dest_type##dest_ptr=0)           

उपयोग:

ObjectPtr ptr; 
DYN_IF(Foo, foo_ptr, ptr) { 
    // foo_ptr is Ptr<Foo> 
} 
DYN_IF(Bar, bar_ptr, ptr) // Works without braces too for single statement 
    // bar_ptr is Ptr<Bar> 

मैं कोड है कि किसी और के द्वारा पढ़ा जा करने के लिए है में सामान की इस तरह की सिफारिश नहीं होगा , लेकिन चूंकि आपने "मैक्रो" शब्द का उल्लेख किया है ...

इसके अलावा, मैं नाटक/ओकैमल शैली में पैटर्न मिलान के साथ कुछ भी करने का नाटक नहीं करता। स्कैला की जांच करें यदि आप ऐसी भाषा चाहते हैं जिसमें सी ++ (अच्छी तरह से, सॉर्ट) और सच्चे पैटर्न मिलान के समान अर्थशास्त्र है।

5

आरटीटीआई का उपयोग कर सी ++ में एक पैटर्न मिलान शैली को अनुकरण करने का प्रयास करना एक साफ विचार है, लेकिन यह कमियों के लिए बाध्य है, क्योंकि हास्केल और मानक एमएल शैली प्रकार कन्स्ट्रक्टर और सी ++ उप-वर्गों के बीच कुछ महत्वपूर्ण अंतर हैं। (नोट: नीचे, मैं मानक ML सिंटैक्स का उपयोग करें, क्योंकि मैं इसके साथ और अधिक आरामदायक है।)

  • हास्केल और मानक ML में, पैटर्न मिलान आप के लिए पैटर्न चर के नेस्टेड मानों बाध्य कर सकते हैं (उदाहरण के लिए पैटर्न a::b::c::ds बांधता सूची के पहले तीन तत्व a, b, और c, और शेष सूची ds पर)। सी ++ में, आपको अभी भी वास्तविक नेस्टेड संरचनाओं में खुदाई करनी होगी, जब तक कि आप या कोई अन्य यहां प्रस्तावित प्रस्तावों की तुलना में कहीं अधिक जटिल मैक्रोज़ के साथ आता है।
  • हास्केल और मानक एमएल में, एक प्रकार का कन्स्ट्रक्टर डेटाटाइप घोषणा datatype 'a option = NONE | SOME of 'a जैसे एक नए प्रकार को परिभाषित करता है: 'a option। रचनाकार NONE और SOME प्रकार नहीं हैं, वे क्रमशः 'a option और 'a -> 'a option के साथ मूल्य हैं। सी ++ में, जब आप टाइपर कन्स्ट्रक्टर अनुकरण करने के लिए Foo और Bar जैसे सबक्लास को परिभाषित करते हैं, तो आपको नए प्रकार मिलते हैं।
  • हास्केल और मानक एमएल में, SOME जैसे रचनाकार प्रथम श्रेणी के कार्य हैं जो डेटाटाइप के मूल्यों का निर्माण करते हैं, जिनके वे संबंधित हैं। उदाहरण के लिए, map SOME में 'a list -> 'a option list है। सी ++ में, टाइप कन्स्ट्रक्टरों को अनुकरण करने के लिए उप-वर्गों का उपयोग करके, आपको यह क्षमता नहीं मिलती है।
  • हास्केल और मानक एमएल में, डेटाटाइप बंद हैं, इसलिए कोई भी मूल घोषणा को बदले बिना अधिक प्रकार के कन्स्ट्रक्टर जोड़ सकता है, और संकलक संकलन समय पर सत्यापित कर सकता है कि पैटर्न मिलान सभी मामलों को संभालता है। सी ++ में, आपको अपनी बेस क्लास को उपclass कर सकते हैं प्रतिबंधित करने के लिए अपने रास्ते से बाहर जाना होगा।

अंत में, क्या आपको सी ++ पॉलिमॉर्फिज्म का उपयोग एक सामान्य तरीके से सिम्युलेटेड पैटर्न मिलान से पर्याप्त लाभ मिल रहा है? मैक्रोज़ का उपयोग सिम्युलेटेड पैटर्न को थोड़ा अधिक संक्षेप में जोड़ने के लिए कर रहा है (जबकि आपके कोड को पढ़ने वाले हर किसी के लिए इसे खराब कर रहा है) सार्थक?

4

हमने सी ++ के लिए एक पैटर्न मिलान लाइब्रेरी को सह-लेखन किया है जो आपको पैटर्न मिलान करने और विश्लेषण को बहुत कुशलता से टाइप करने की अनुमति देता है। मैक 7 नामक लाइब्रेरी को बीएसडी लाइसेंस के तहत जारी किया गया है और गिटहब पर उपलब्ध है: https://github.com/solodon4/Mach7। आप वीडियो, पोस्टर, स्लाइड, कागजात के साथ-साथ स्रोत कोड भी पा सकते हैं। यह वर्तमान में जीसीसी 4.4+, क्लैंग 3.4+ और विजुअल सी ++ 2010+ का समर्थन करता है। अपने भंडार के खिलाफ गिटहब मुद्दे जमा करके लाइब्रेरी के बारे में प्रश्न पूछने के लिए स्वतंत्र महसूस करें।

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