क्या C ++ फ़ंक्शन कॉन्स्टैक्स को चिह्नित करना कभी भी बुरा है?


26

एक बहुत ही तुच्छ कार्य को देखते हुए,

int transform(int val) {
    return (val + 7) / 8;
}

यह बहुत स्पष्ट होना चाहिए कि इस फ़ंक्शन को फ़ंक्शन में बदलना आसान है constexpr, जिससे मुझे constexprचर का उपयोग करते समय इसका उपयोग करने की अनुमति मिलती है , जैसे:

constexpr int transform(int val) {
    return (val + 7) / 8;
}

मेरी धारणा यह है कि यह कड़ाई से सुधार है, क्योंकि फ़ंक्शन को अभी भी गैर- constexprसंदर्भ में कहा जा सकता है, और अब इसका उपयोग संकलन-समय स्थिर चर को परिभाषित करने में मदद करने के लिए भी किया जा सकता है।

मेरा प्रश्न यह है कि क्या ऐसी स्थितियाँ हैं जहाँ यह एक बुरा विचार है? जैसे, इस फ़ंक्शन को करने से constexpr, क्या मैं कभी ऐसी स्थिति का सामना कर सकता हूं जहां यह फ़ंक्शन अब किसी विशेष परिस्थिति में उपयोग करने योग्य नहीं होगा, या जहां यह दुर्व्यवहार करेगा?


1
केवल एक चीज जिसके बारे में मैं सोच सकता था वह थी संकलक कीड़े। यह संभव है कि एक पुनरावर्ती कॉन्स्टैक्स फ़ंक्शन कॉल वास्तव में धीमी गति से संकलित कदम या यहां तक ​​कि स्मृति दुर्घटना से बाहर एक संकलक का कारण हो सकता है।
ज़ैन लिंक्स

जवाबों:


19

यह तभी मायने रखता है जब फ़ंक्शन सार्वजनिक इंटरफ़ेस का हिस्सा है, और आप अपने एपीआई बाइनरी-संगत के भविष्य के संस्करणों को रखना चाहते हैं। उस स्थिति में, आपको ध्यान से सोचना होगा कि आप अपने एपीआई को कैसे विकसित करना चाहते हैं, और जहां आपको भविष्य में बदलाव के लिए विस्तार बिंदुओं की आवश्यकता है।

यह constexprक्वालिफायर को एक अपरिवर्तनीय डिजाइन निर्णय बनाता है । आप अपने API में असंगत परिवर्तन के बिना इस योग्यता को नहीं निकाल सकते। यह भी सीमित करता है कि आप उस फ़ंक्शन को कैसे लागू कर सकते हैं, जैसे कि आप इस फ़ंक्शन के भीतर कोई लॉगिंग नहीं कर पाएंगे। हर तुच्छ कार्य अनंत काल में तुच्छ नहीं रहेगा।

इसका मतलब है कि आपको उन constexprकार्यों के लिए अधिमानतः उपयोग करना चाहिए जो स्वाभाविक रूप से शुद्ध कार्य हैं, और यह वास्तव में संकलन समय (जैसे टेम्पलेट मेटाप्रोग्रामिंग) के लिए उपयोगी होगा। केवल फ़ंक्शंस को कॉन्स्ट्रेक्ट बनाना अच्छा नहीं होगा क्योंकि वर्तमान इम्प्लीमेंटेशन कॉन्स्ट्रेप-सक्षम होने के लिए होता है।

जहां संकलन-समय का मूल्यांकन आवश्यक नहीं है, आंतरिक लिंक के साथ इनलाइन फ़ंक्शन या फ़ंक्शन का उपयोग करना अधिक उचित होगा constexpr। इन सभी वेरिएंट में सामान्य रूप से फ़ंक्शन बॉडी "सार्वजनिक" है और कॉल स्थान के समान संकलन इकाई में उपलब्ध है।

यदि विचाराधीन फ़ंक्शन स्थिर, सार्वजनिक API का हिस्सा नहीं है, तो यह एक समस्या से कम है क्योंकि आप मनमाने ढंग से डिजाइन को बदल सकते हैं। लेकिन चूंकि अब आप सभी कॉल साइटों को नियंत्रित करते हैं, इसलिए "केवल मामले में" एक फ़ंक्शन कॉन्स्ट्रेप को चिह्नित करना आवश्यक नहीं है। आप जानते हैं कि आप इस फ़ंक्शन का उपयोग किसी संदर्भ में कर रहे हैं। अनावश्यक रूप से प्रतिबंधात्मक क्वालीफायर जोड़ना फिर भी अतिक्रमण माना जा सकता है।


12

एक समारोह के रूप में चिह्नित करना constexpr भी इसे एक इनलाइन फ़ंक्शन बनाता है also [dcl.constexpr] / 1

एक फ़ंक्शन या स्थैतिक डेटा सदस्य को कॉन्स्ट्रेक्स स्पेसियर के साथ घोषित किया गया है, जो कि एक इनलाइन फ़ंक्शन या चर (7.1.6) है।

inlineबदले में, इसका मतलब है कि आपको हर अनुवाद इकाई में उस फ़ंक्शन की परिभाषा को शामिल करना होगा जिसमें इसका उपयोग किया जा सकता है। वह मूल रूप से मतलब हैconstexpr कार्य या तो होने चाहिए:

  1. एक अनुवाद इकाई में उपयोग करने के लिए प्रतिबंधित है, या
  2. एक हेडर में परिभाषित किया गया।

अधिकांश विशिष्ट फ़ंक्शंस जिन्हें आप हेडर में घोषित करना चाहते हैं और एक स्रोत फ़ाइल में परिभाषित करते हैं (और कुछ भी जो उनका उपयोग करता है उनमें हेडर शामिल है, फिर उस स्रोत की ऑब्जेक्ट फ़ाइल के खिलाफ लिंक) constexpr बस काम नहीं करेगा।

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

एक constexprफ़ंक्शन भी कुछ मायनों में प्रतिबंधित है, इसलिए कुछ कार्यों के लिए यह एक विकल्प नहीं हो सकता है। प्रतिबंधों में शामिल हैं:

  1. आभासी कार्य नहीं हो सकतेconstexpr
  2. इसका वापसी प्रकार एक 'शाब्दिक प्रकार' होना चाहिए (उदाहरण के लिए, गैर-ट्रिटिंग सीज़र या डस्टर के साथ कोई ऑब्जेक्ट नहीं)।
  3. इसके सभी पैरामीटर शाब्दिक प्रकार के होने चाहिए।
  4. फ़ंक्शन बॉडी में एक tryब्लॉक नहीं हो सकता ।
  5. इसमें एक गैर-शाब्दिक प्रकार की एक वैरिएबल परिभाषा या स्थिर या थ्रेड स्टोरेज अवधि के साथ कुछ भी नहीं हो सकता है।

मैंने कुछ चीजों को अस्पष्ट कर दिया है (उदाहरण के लिए, यह भी एक gotoया एक asmबयान नहीं हो सकता है ), लेकिन आपको यह विचार मिलता है - काफी कुछ चीजों के लिए, यह सिर्फ काम नहीं करेगा।

निचला रेखा: हाँ, ऐसी बहुत सी स्थितियाँ हैं जहाँ यह एक बुरा विचार होगा।


"यह वर्चुअल नहीं होना चाहिए (C ++ 20 तक)" मैं सोच रहा हूं कि वर्चुअल फ़ंक्शन कैसे हो सकता है? कंपाइलर क्या करते हैं?
जस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.