टंकण का उपयोग कब करें?


14

मैं थोड़ा उलझन में हूँ कि क्या और कब मुझे C ++ में टाइपडिफ का उपयोग करना चाहिए। मुझे लगता है कि यह पठनीयता और स्पष्टता के बीच संतुलन का कार्य है।

यहां पर बिना किसी टाइपराइफ के एक कोड सैंपल दिया गया है:

int sum(std::vector<int>::const_iterator first, 
        std::vector<int>::const_iterator last)
{
    static std::map<std::tuple<std::vector<int>::const_iterator,
                               std::vector<int>::const_iterator>,
                    int> lookup_table;

    std::map<std::tuple<std::vector<int>::const_iterator,
                        std::vector<int>::const_iterator>, int>::iterator lookup_it =
        lookup_table.find(lookup_key);

    if (lookup_it != lookup_table.end())
        return lookup_it->second;            

    ...
}

बहुत बदसूरत आईएमओ। तो मैं इसे टाइप करने के लिए फंक्शन के भीतर कुछ टाइपराइफ जोड़ूंगा ताकि इसे अच्छे से देखा जा सके:

int sum(std::vector<int>::const_iterator first, 
        std::vector<int>::const_iterator last)
{
    typedef std::tuple<std::vector<int>::const_iterator,
                       std::vector<int>::const_iterator> Lookup_key;
    typedef std::map<Lookup_key, int> Lookup_table;

    static Lookup_table lookup_table;

    Lookup_table::iterator lookup_it = lookup_table.find(lookup_key);

    if (lookup_it != lookup_table.end())
        return lookup_it->second;            

    ...
}

कोड अभी भी थोड़ा अनाड़ी है, लेकिन मुझे सबसे अधिक बुरे सपने से छुटकारा मिलता है। लेकिन अभी भी सदिश वेक्टर पुनरावृत्तियाँ हैं, इस संस्करण से छुटकारा मिल जाता है:

typedef std::vector<int>::const_iterator Input_iterator;

int sum(Input_iterator first, Input_iterator last)
{
    typedef std::tuple<Input_iterator, Input_iterator> Lookup_key;
    typedef std::map<Lookup_key, int> Lookup_table;

    static Lookup_table lookup_table;

    Lookup_table::iterator lookup_it = lookup_table.find(lookup_key);

    if (lookup_it != lookup_table.end())
        return lookup_it->second;            

    ...
}

यह साफ दिखता है, लेकिन क्या यह अभी भी पठनीय है?

मुझे एक टंकण का उपयोग कब करना चाहिए? जैसे ही मेरे पास एक बुरा सपना है? जैसे ही यह एक से अधिक बार होता है? मैं उन्हें कहां रखूं? क्या मुझे उन्हें फ़ंक्शन हस्ताक्षरों में उपयोग करना चाहिए या उन्हें कार्यान्वयन में रखना चाहिए?


1
डुप्लिकेट नहीं, लेकिन कुछ हद तक मेरे प्रश्न से संबंधित है। प्रोग्रामर.स्टैकएक्सचेंज.
com

typedef Input_iterator std::vector<int>::const_iterator;बैकवर्ड है
प्रति जोहानसन

1
पठनीयता और स्पष्टता के बीच अंतर है?
नील

जब #defineबहुत अच्छा हो
थॉमस एडिंग

जवाबों:


6

आपका अंतिम उदाहरण बहुत पठनीय है, लेकिन यह इस बात पर निर्भर करता है कि आप टाइपराइफ को कहां परिभाषित करते हैं। स्थानीय स्कोप टाईपडेफ़्स (जैसे आपके दूसरे उदाहरण में) IMVHO लगभग हमेशा एक जीत है।

मुझे अभी भी आपका तीसरा उदाहरण सबसे अच्छा लगता है, लेकिन आप नामकरण के बारे में सोचना चाहते हैं, और पुनरावृत्तियों को ऐसे नाम दे सकते हैं जो कंटेनर का इरादा बताते हैं।

एक अन्य विकल्प यह होगा कि आप अपने फंक्शन से एक खाका बना लें, ताकि यह विभिन्न कंटेनरों के साथ भी काम करे। इस के समान

template <typename Input_iterator> ... sum(Input_iterator first, Input_iterator last) 

जो एसटीएल की भावना में बहुत अधिक है।


2

typedefएक समारोह के बराबर चर घोषणा के रूप में सोचो : यह वहाँ है तो आप ...

  • ... उसी प्रकार (जो आपके पहले दो उदाहरण करते हैं) का पुन: उपयोग करते समय खुद को दोहराना नहीं है।
  • ... प्रकार के गोर विवरण को छुपा सकते हैं ताकि वे हमेशा प्रदर्शन पर न हों।
  • ... सुनिश्चित करें कि प्रकार का परिवर्तन हर उस जगह पर प्रतिबिंबित होता है जिसका वे उपयोग कर रहे हैं।

व्यक्तिगत रूप से, मैं इस बात पर ध्यान नहीं देता कि मुझे std::vector<int>::const_iteratorबार-बार लंबे प्रकार के नाम पढ़ने हैं ।

आपका तीसरा उदाहरण अनावश्यक रूप से खुद को नहीं दोहराता है और पढ़ने में आसान है।


1

typedefघोषणाएं अनिवार्य रूप से एनकैप्सुलेशन के समान उद्देश्य की सेवा करती हैं। इस कारण से, वे लगभग हमेशा एक हेडर फ़ाइल में सबसे अच्छा फिट होते हैं, जो आपकी कक्षाओं के समान नामकरण परंपराओं का पालन करते हैं, क्योंकि:

  • यदि आपको आवश्यकता है typedef, तो संभावना है कि कॉल करने वाले भी, विशेष रूप से आपके उदाहरण में जहां तर्कों में इसका उपयोग किया जाता है।
  • यदि आपको किसी भी कारण से प्रकार को बदलने की आवश्यकता है, जिसमें इसे अपनी कक्षा के साथ प्रतिस्थापित करना शामिल है, तो आपको इसे केवल एक ही स्थान पर करना होगा।
  • बार-बार जटिल प्रकार लिखने के कारण यह आपको गलतियों का कम संकेत देता है।
  • यह अनावश्यक कार्यान्वयन विवरण छिपाता है।

एक तरफ के रूप में, आपका संस्मरण कोड बहुत अधिक क्लीनर होगा यदि आपने इसे आगे सार किया है, जैसे:

if (lookup_table.exists(first, last))
    return lookup_table.get(first, last);

आपका सुझाव क्लीनर लग सकता है, लेकिन यह दो बार लुकअप करके समय बर्बाद करता है।
डेरेक लेडबेटर

हां, यह एक जानबूझकर व्यापार बंद था। इसे एक ही लुकअप के साथ करने के तरीके हैं जो लगभग साफ हैं, हालांकि, खासकर यदि आप थ्रेड सुरक्षा के बारे में चिंतित नहीं हैं।
कार्ल बेवफेल्ड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.