2016-08-27 8 views
12

मैं अपना खुद का signal/स्लॉट (पर्यवेक्षक पैटर्न, क्यूटी शैली) तंत्र लागू कर रहा हूं, इसलिए मेरे पास property हो सकता है जो सूचित करता है ... सामान ... यह बदल गया है।कार्यान्वयन संकेत (पर्यवेक्षक पैटर्न): उत्परिवर्तनीय या const_cast आवश्यक है?

मुझे लगता है कि सी ++ 11 एक बहुत ही सस्ता और फीचरपूर्ण कार्यान्वयन संभव बनाने के लिए आवश्यक सब कुछ प्रदान करता है। "मुद्दा" मैं दौड़ रहा हूं अगर मैं const ऑब्जेक्ट के सिग्नल पर "कनेक्ट" करना चाहता हूं, तो मुझे signal::connect फ़ंक्शन को कॉन्स होने की आवश्यकता है, लेकिन कॉलबैक/पर्यवेक्षकों की सूची संशोधित करें। इसे ठीक करने के दो सरल तरीके हैं:

  1. const_castconnect के अंदर सूचियां।
  2. सूचियां mutable बनाएं।

दोनों एक ही बात की तरह मुझे लगता है (और इस से पहले पूछा गया है, जैसे this question में), और बिल्कुल ठीक तार्किक, लेकिन शैलीगत संदिग्ध। इसलिए सवाल है। क्या इसके आसपास कोई रास्ता है या क्या यह const_cast/mutable का वास्तव में उचित उपयोग है?

कुछ prelimenary कोड मैं अब है के रूप में:

template<typename... ArgTypes> 
class signal 
{ 
public: 
    template<typename Callable> 
    void connect(Callable&& callback) const 
    { 
    std::lock_guard<std::mutex> lock(slots_mutex); 
    slots.emplace_back(callback); 
    } 

    void emit(ArgTypes... arguments) const 
    { 
    std::lock_guard<std::mutex> lock(slots_mutex); 
    for(auto&& callback : slots) 
    { 
     callback(arguments...); 
    } 
    } 

private: 
    // mutable here allows to connect to a const object's signals 
    mutable std::vector<std::function<void(ArgTypes...)>> slots; 
    std::mutex slots_mutex; 

}; 

नोट मैं इस कोड का परीक्षण नहीं किया; यह सिर्फ मेरे वर्तमान दिमाग की प्रतिबिंब है।

+2

गैर-परीक्षण कोड ... tsk tsk ... –

+0

@ अरनाव मैं सचमुच परीक्षण लिख रहा हूं, मुझे बस इस डिजाइन को इस तरह से हल करने की आवश्यकता है: पी। – rubenvb

+0

मुझे डर है कि मुझे समझ में नहीं आता कि क्यों 'सिग्नल' को 'const' विधियों का खुलासा करना चाहिए। क्यों 'सिग्नल' के उपयोगकर्ता को यह तय नहीं करना चाहिए कि वे इसे उत्परिवर्तनीय (या नहीं) चाहते हैं? –

उत्तर

9

mutable आमतौर पर ऐसे मामलों के लिए बेहतर विकल्प होता है।

से बचें (const) कास्टिंग जब भी आप कर सकते हैं, यह अपरिभाषित व्यवहार मारने के लिए होने का खतरा है, जबकि mutable नहीं 1) होने की गारंटी है।


mutable वर्ग के सदस्यों उत्सर्जित कोड के लिए उदाहरण के लिए .text खंड जाने के लिए नहीं की गारंटी है।

2

इसे ठीक करने के दो सरल तरीके हैं:

  1. const_castconnect अंदर सूचियों।
  2. सूचियां mutable बनाएं।

वास्तव में वहाँ एक तिहाई विकल्प है (जो एक सामान्य प्रयोजन होने वैकल्पिक हल, सी ++ था mutable कीवर्ड उपलब्ध नहीं) - आप वाक्य-वस्तु से बाहर चिंतित डेटा को स्थानांतरित कर सकते हैं:

class X 
{ 
    mutable int   i1_; 

    // Data pointed to by i2_ semantically belongs to this object 
    // but doesn't constitute a syntactical part of it so it is not 
    // subject to const-correctness checks by the compiler. 
    std::unique_ptr<int> i2_; 

public: 
    void constFunc() const { 
     i1_ = 123; 
     *i2_ = 456; 
    } 
}; 

इस अतिरिक्त विकल्प की उपलब्धता के बावजूद, मैं अभी भी πάντα ῥεῖ के answer से सहमत हूं कि mutable कीवर्ड ऐसे मामलों के लिए सही विकल्प है। यह स्पष्ट रूप से मानकीकृत तरीके से दस्तावेज करता है (उदाहरण के लिए grepped की अनुमति देता है) कि इस वर्ग के अवधारणा const संचालन तकनीकी रूप से गैर-उत्परिवर्तन नहीं हो सकता है।यह जानना अच्छा है, उदाहरण के लिए, जब कक्षा के const कार्यों की थ्रेड सुरक्षा से संबंधित हो।

0

सिग्नल :: कनेक्टसिग्नल :: स्लॉट संशोधित करता है। इसलिए, मुझे लगता है कि केवल एक चीज जो आपको करने की ज़रूरत है वह आपके डिजाइन को बदल देती है। सिग्नल :: कनेक्ट करें म्यूटेबल हो और कॉलर्स म्यूटेबल सिग्नल पॉइंटर्स होल्ड करें।

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