2010-05-05 13 views
11

में सीएलआर (.NET) प्रतिनिधियों/ईवेंट हैंडलर के रूप में लैम्ब्डा एक्सप्रेशन सीएलआर इवेंट हैंडलर के रूप में विजुअल सी ++ 2010 में नए लैम्ब्डा एक्सप्रेशन का उपयोग करना संभव है?विज़ुअल सी ++ 2010

SomeEvent += gcnew EventHandler(
    [] (Object^ sender, EventArgs^ e) { 
     // code here 
    } 
); 

यह निम्न त्रुटि संदेश में परिणाम:

त्रुटि C3364: 'सिस्टम :: eventhandler': मैं निम्नलिखित कोड की कोशिश की है प्रतिनिधि निर्माता के लिए अमान्य तर्क; प्रतिनिधि लक्ष्य को सदस्य फ़ंक्शन

क्या मैं असंभव प्रयास कर रहा हूं, या बस मेरा वाक्यविन्यास गलत है?

+0

यहां पोस्ट किया गया मेरा समाधान "Lambda2Delegate" जांचें http://stackoverflow.com/a/26552573/2604941 –

उत्तर

7

कोई नहीं कर सकता, सी ++/सीएलआई कंपाइलर को लैम्ब्डा सिंटैक्स को स्वीकार करने के लिए अपडेट नहीं किया गया था। काफी हद तक विडंबनात्मक बीटीडब्ल्यू ने हेड-स्टार्ट दिया जो प्रबंधित कोड था।

+0

यह वास्तव में है। मुझे आश्चर्य है कि कैप्चर क्लॉज सेमेन्टिक्स के साथ ऐसा कुछ करना है, जो सीएलआर में मौजूद नहीं है। जहां तक ​​मैं समझता हूं कि सी # लैम्बदास कुछ हैं [', और यह]' - जैसा कि लैम्ब्डा अपने माता-पिता के दायरे में जो कुछ भी संशोधित कर सकता है, इसलिए वे केवल यह अनिवार्य कर सकते थे कि सी ++ लैम्बडास में ऐसे कैप्चर क्लॉज होना चाहिए। –

+0

यह बहुत बुरा है, यह फ़ंक्शन के अंदर एक फेंकने वाली कक्षा के साथ थोड़ा गन्दा दिखता है जो एक सदस्य फ़ंक्शन रखने के लिए हैंडलर बनाता है। :/ – absence

+0

सीएलआर अप्रबंधित पॉइंटर्स से निपट सकता है (जो है और संदर्भों का अनुवाद किया जाता है), इसलिए यह किया जा सकता है - यह सिर्फ सत्यापित नहीं होगा। मेरा मानना ​​है कि यह ऐसा कुछ नहीं है जिसे वे लागू करने के लिए समय लेना चाहते थे। मेरे पास इसके लिए एक कनेक्ट फीचर अनुरोध लॉग है: https://connect.microsoft.com/VisualStudio/feedback/details/524356/add-managed-lambdas-to-c-cli - अगर आप इसे चाहते हैं तो upvote। –

-1

यह पृष्ठ सी के लिए ++ lambdas के कुछ उदाहरण हैं:

http://msdn.microsoft.com/en-us/library/dd293608%28v=VS.100%29.aspx

माइक्रोसॉफ्ट VS2010 सी ++ सुधार देखने की तरह वे वास्तव में C++0x lambda spec लागू। जैसे कि वे पूरी तरह से अप्रबंधित हैं और lambda प्रकार के हैं।

माइक्रोसॉफ्ट प्रलेखन में कुछ भी नहीं है जो सी ++ लैम्बडास को सीएलआर लैम्बडास के रूप में उपयोग करने की संभावना पर संकेत देता है। इस स्तर पर मुझे यह कहना है कि आप प्रबंधित प्रतिनिधियों के लिए हैंडलर के रूप में सी ++ लैम्बडा का उपयोग नहीं कर सकते हैं।

9

निम्नलिखित मेरा समाधान है जो एक को लैम्ब्स को लपेटने की अनुमति देता है (साथ ही किसी भी फ़ंक्शन ऑब्जेक्ट्स - यानी operator() को कुछ भी कहा जा सकता है) प्रतिनिधियों में। इसमें कुछ सीमाएं हैं - विशेष रूप से, यह ट्रैकिंग संदर्भ पैरामीटर (% सी ++/सीएलआई में ref/out सी #) में प्रतिनिधियों का समर्थन नहीं करती है; और प्रतिनिधि द्वारा प्राप्त किए जा सकने वाले मापदंडों की संख्या पर इसकी ऊपरी सीमा है (क्योंकि वीसी ++ 2010 वैरगा टेम्पलेट्स का समर्थन नहीं करता है) - हालांकि कोड जितना चाहें उतना समर्थन करने के लिए छोटे से समायोजित किया जा सकता है।

#pragma once 

#include <new> 
#include <type_traits> 

namespace detail 
{ 
    struct return_type_helper 
    { 
    private: 

     template<class D> 
     struct dependent_false { enum { value = false }; }; 

     template <class D> 
     struct illegal_delegate_type 
     { 
      static_assert(dependent_false<D>::value, "Delegates with more than 2 parameters, or with parameters of tracking reference types (T%), are not supported."); 
     }; 

     struct anything 
     { 
      template<class T> 
      operator T() const; 
     }; 

    public: 

     template<class D> 
     static decltype(static_cast<D^>(nullptr)()) dummy(int(*)[1]); 

     template<class D> 
     static decltype(static_cast<D^>(nullptr)(anything())) dummy(int(*)[2]); 

     template<class D> 
     static decltype(static_cast<D^>(nullptr)(anything(), anything())) dummy(int(*)[3]); 

     template <class D> 
     static illegal_delegate_type<D> dummy(...); 
    }; 


    template<class Func, class Aligner = char, bool Match = (std::tr1::alignment_of<Func>::value == std::tr1::alignment_of<Aligner>::value)> 
    struct aligner 
    { 
     static_assert(Match, "Function object has unsupported alignment"); 
    }; 

    template<class Func, class Aligner> 
    struct aligner<Func, Aligner, true> 
    { 
     typedef Aligner type; 
    }; 

    template<class Func> 
    struct aligner<Func, char, false> : aligner<Func, short> 
    { 
    }; 

    template<class Func> 
    struct aligner<Func, short, false> : aligner<Func, int> 
    { 
    }; 

    template<class Func> 
    struct aligner<Func, int, false> : aligner<Func, long> 
    { 
    }; 

    template<class Func> 
    struct aligner<Func, long, false> : aligner<Func, long long> 
    { 
    }; 

    template<class Func> 
    struct aligner<Func, long long, false> : aligner<Func, double> 
    { 
    }; 

    template<class Func> 
    struct aligner<Func, double, false> : aligner<Func, void*> 
    { 
    }; 


    template<class F> 
    ref class lambda_wrapper 
    { 
    public: 

     lambda_wrapper(const F& f) 
     { 
      pin_ptr<F> pf = (interior_ptr<F>)&f_storage; 
      new(pf) F(f); 
     } 

     ~lambda_wrapper() 
     { 
      pin_ptr<F> pf = (interior_ptr<F>)&f_storage; 
      pf->~F(); 
     } 

     template <class D> 
     operator D^() 
     { 
      D^ d = nullptr; 
      return gcnew D(this, &lambda_wrapper<F>::invoke<decltype(return_type_helper::dummy<D>(0))>); 
     } 

    private: 

     template<class T> 
     [System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential, Size = sizeof(T))] 
     value struct embedded_storage 
     { 
     private: 
      typename aligner<T>::type dummy; 
     }; 


     embedded_storage<F> f_storage; 

     template<class R> 
     R invoke() 
     { 
      pin_ptr<F> pf = (interior_ptr<F>)&f_storage; 
      return (*pf)(); 
     } 

     template<class R, class A1> 
     R invoke(A1 a1) 
     { 
      pin_ptr<F> pf = (interior_ptr<F>)&f_storage; 
      return (*pf)(a1); 
     } 

     template<class R, class A1, class A2> 
     R invoke(A1 a1, A2 a2) 
     { 
      pin_ptr<F> pf = (interior_ptr<F>)&f_storage; 
      return (*pf)(a1, a2); 
     } 
    }; 
} 

template<class F> 
detail::lambda_wrapper<F>^ make_delegate(F f) 
{ 
    return gcnew detail::lambda_wrapper<F>(f); 
} 

नमूना उपयोग:

Func<int, String^, int>^ f2 = make_delegate([&](int x, String^ y) -> int { 
    Console::WriteLine("Func {0} {1}", x, y); 
    return 2; 
}); 

हालांकि यह तकनीकी रूप से आप क्या चाहते हैं करता है, व्यावहारिक अनुप्रयोगों के लिए कुछ हद तक इस तथ्य के कारण है कि C++ 0x lambdas सादा वर्गों में विस्तार कर रहे हैं, नहीं ref या तक सीमित हैं value वाले। चूंकि सादे वर्गों में सी ++/सीएलआई में प्रबंधित प्रकार नहीं हो सकते हैं (यानी ऑब्जेक्ट हैंडल प्रकार के कोई सदस्य नहीं, ट्रैकिंग संदर्भ प्रकार के कोई सदस्य नहीं हैं, और value class प्रकार के कोई सदस्य नहीं हैं), इसका मतलब है कि लैम्बडा उन प्रकारों के किसी भी चर को कैप्चर नहीं कर सकता है। संदर्भों को ट्रैक करने के लिए मुझे कोई कामकाज नहीं है। value class के लिए, आप इसे एक अप्रबंधित पॉइंटर ले सकते हैं (pin_ptr यदि आवश्यक हो), और उसे कैप्चर करें।

ऑब्जेक्ट हैंडल के लिए, आप उन्हें gcroot<T> में स्टोर कर सकते हैं, और इसे कैप्चर कर सकते हैं - लेकिन मेरे परीक्षणों में, gcroot<T> के माध्यम से सदस्य तक पहुंचने से सादे ऑब्जेक्ट हैंडल का उपयोग करके इसे 40x गुना धीमा कर दिया जाता है। यह वास्तव में एक कॉल के लिए पूर्ण माप में बहुत अधिक नहीं है, लेकिन किसी लूप में बार-बार कहा जाता है - कहें, अधिकांश LINQ एल्गोरिदम - यह एक हत्यारा होगा। लेकिन ध्यान दें कि यह केवल तब लागू होता है जब आपको लैम्ब्डा में एक हैंडल कैप्चर करने की आवश्यकता होती है! यदि आप इसे एक अनुमानित इनलाइन लिखने के लिए या काउंटर अपडेट करने के लिए उपयोग करते हैं, तो यह ठीक काम करेगा।

+0

धन्यवाद! मैं प्रदर्शन प्रभाव को दिमाग में रखूंगा। – absence

+0

यह एलएनके 2022 के साथ असफल प्रतीत होता है अगर मैं इसे उसी प्रकार के साथ लैम्बडास के लिए बुलाता हूं लेकिन जो विभिन्न चीजों को कैप्चर करता है। मुझे लगता है कि जेनरेट प्रकार का आकार अलग है जबकि टाइप समान है। क्या इसके लिए कोई फिक्स है या क्या मैं वैसे भी अपने सिद्धांत के आधार पर आधार का तरीका हूं? – Sarien

+0

सारीन, आप का मतलब क्या है "एक ही प्रकार के भेड़ के बच्चे अलग-अलग चीजों को कैप्चर करते हैं"? प्रत्येक सी ++ लैम्ब्डा का अपना अनूठा प्रकार होता है, भले ही हस्ताक्षर मिलते हैं, और यहां तक ​​कि यदि कैप्चर सूचियां मेल खाते हैं। –

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