2015-12-02 7 views
6

मुझे कभी-कभी ऐसे मामलों का सामना करना पड़ता है जहां यह एक चर के लिए const होना चाहिए, लेकिन केवल इसके दायरे के बाद के हिस्से के लिए। उदाहरण के लिए, एक ब्लॉक के पहले भाग मूल्य निर्धारित कर सकते हैं, और अगर यह स्पष्ट है कि हम "किया" कर रहे थे कि चर की स्थापना थे बाकी की पठनीयता में सुधार किया जा सकता है -निरंतर, लेकिन केवल इस दायरे के शेष के लिए

void foo() { 
    int n; 
    // Do things that result in initialization of n 

    freeze n; // Imaginary construct that declares "n" const for rest of scope 

    // Later steps that depend on 'n' but do not change it 
} 

कोई सी ++ मुहावरा है कि कैप्चर है यह पैटर्न? बेशक ब्लॉक के बाद के हिस्से को एक अलग समारोह में ले जाया जा सकता है, लेकिन क्या इसे चीजों को चारों ओर घुमाने के बिना किया जा सकता है?

+1

क्या यह उस तर्क को समाहित करने के लिए और अधिक समझ में नहीं आता है जो 'एन' को अपने स्वयं के कार्य में उत्पन्न करता है? और फिर बस 'const int n = gimme_an_n(); '। आप * lambdas के साथ उस इनलाइन कर सकते हैं, लेकिन ... क्या आप चाहते हैं? – paddy

उत्तर

4

के बजाय अपरिवर्तनीय भाग के रूप में लपेटकर


एक अन्य विकल्प अपने कार्य होने के लिए है लैम्ब्डा, प्रारंभिक भाग को लैम्ब्डा में कैसे लपेटें और इसे const int के रूप में प्राप्त करें? फिर म्यूटेबल int n को बदलने का कोई मौका नहीं है।

void foo() { 
    const int n = []() { ; 
     // Do things that result in initialization of n 
     return initialized_n; 
    }();  

    // Later steps that depend on 'n' but do not change it 
} 
0

@PSkocik's answer (अब हटाया गया) के समान दृष्टिकोण का उपयोग करके, आप अज्ञात लैम्बडा में वांछित चर को कैप्चर कर सकते हैं और बाद वाले को निष्पादित कर सकते हैं। तुम भी इसके लिए एक variadic मैक्रो निर्धारित कर सकते हैं, तो आप एक अपेक्षाकृत "क्लीन" सिंटैक्स का उपयोग एक से अधिक चर पर कब्जा कर सकते हैं:

#include <iostream> 

#define WITH_CONST(...) [&, __VA_ARGS__]() 
#define DO(); 

void foo() { 
    int n{1}, m{2}, z{3}; 
    WITH_CONST(n, m) // captured variables are immutable in the scope below 
    { 
     //++n; // compile-time error 
     //++m; // compile-time error 
     ++z; // z is mutable, can modify 
     std::cout << n << " " << m << " " << z << std::endl; 
    } 
    DO; 

    // n and m are not constant anymore 
    ++n; 
    ++m; 
    std::cout << n << " " << m << " " << z << std::endl; 
} 

int main() 
{ 
    foo(); 
} 

Live on Coliru

यह के सभी के लिए चर निरंतर नहीं है दायरे के शेष, लेकिन यह आपको उस दायरे को नियंत्रित करने देता है जिसमें वे स्थिर हैं, और बाद में, अंतराल को संलग्न क्षेत्र के अंत तक बढ़ाया जा सकता है।

6

आपका "फ्रीज" कोड दिखाई दे सकता है जैसे:

const int &refN = n; 

और फिर आप n के बजाय refN का उपयोग करें। आप नामों को चारों ओर बदल सकते हैं।

अधिक जटिल समाधान हैं लेकिन आपको वास्तव में खुद से पूछना है कि लाभ दर्द के लायक है या नहीं। यदि आपका फ़ंक्शन इतना जटिल है कि आप एक नज़र में नहीं देख सकते हैं कि आपने n संशोधित किया है तो आपको अपना कोड दोबारा करने की आवश्यकता है।


उदाहरण के लिए

, n को छिपाने के लिए आप कर सकता है:

{ 
const int &_tmp = n; 
const int &n = _tmp; 

// rest of code 

} 

लेकिन आप अपने आप से पूछना अगर यह इसके लायक है। जो भी आप कोड को पढ़ते हैं, उसके बाद कोई आश्चर्यचकित होगा कि आप क्या धूम्रपान कर रहे थे।

const int n = setup_n(); 

जहां एक और कार्य करने के लिए तर्क ऑफलोड, या एक लैम्ब्डा:

const int n = [](){ 
    // ...logic... 
    return finalized_value; 
}(); 
संबंधित मुद्दे