2017-04-24 6 views
10

मुझे enum { my_const = 123; } के साथ मेरे स्थिरांक को परिभाषित करने के लिए उपयोग किया जाता है, क्योंकि कक्षाओं में static constexpr का उपयोग कक्षा परिभाषा के बाहर कुछ कोड की आवश्यकता है (this question देखें)। लेकिन - समारोह निकायों में क्या? हाल ही में मैंने देख रहा है लोगों को अभी उनके कार्यों में constexpr चर होने (यहां तक ​​कि const करने के लिए उन्हें वास्तव में परेशान कर नहीं), और मैं सोच रहा था कि क्या मैं एक मूर्ख है जो अपनेमुझे किसी फ़ंक्शन के भीतर निरंतर के लिए कौन सा प्राथमिकता देना चाहिए: constexpr const या enum?

int foo(int x) 
{ 
    enum : int { bar = 456 }; 
    return x + bar; 
} 

तो साथ बार के पीछे कर रहा हूँ, मेरे सवाल यह है: क्या एनएक्स के कॉन्सएक्सप्रैर चर के बजाए फ़ंक्शन निकायों के उपयोग के लिए कोई लाभ है?

+3

जब सी ++ 1z बाहर आता है (शायद यह जुलाई) और मुख्यधारा के कंपाइलर समर्थन प्राप्त करता है, तो कक्षा में 'स्थैतिक constexpr' चर का उपयोग करना संभव होगा क्योंकि वे स्वचालित रूप से इनलाइन हो जाएंगे। लेकिन कार्यों के लिए, क्या आपका मतलब है कि आप अपने स्थिरांक के लिए एक समारोह के अंदर 'enum' घोषित करते हैं? –

+0

@DanielH: हाँ, संपादन देखें। – einpoklum

+3

मुझे लगभग निश्चित है कि फ़ंक्शन बॉडी के अंदर कोई लाभ नहीं है (गैर स्थैतिक चर को किसी भी लिंक की आवश्यकता नहीं होगी, और स्थिर लोग स्वयं फ़ंक्शन को साझा कर सकते हैं), और वास्तव में मुझे लगता है कि C++ मानक द्वारा इसकी अनुमति नहीं है (भले ही कुछ कंपाइलर इसे विस्तार के रूप में अनुमति दे सकें)। विशेष रूप से, मुझे आपके कोड को संकलित करने के लिए g ++ (संस्करण 6.3) नहीं मिल सकता है। मैं इस टिप्पणी के बजाए इसे उत्तर देने के लिए बिल्कुल निश्चित नहीं हूं, लेकिन अगर यह गलत है तो मुझे आश्चर्य होगा। –

उत्तर

18

आप गलती से या bar के प्रयोजन के बल ओडीआर-अस्तित्व पर अगर यह एक constexpr int bar = 456; था, यह संभव नहीं enum : int { bar = 456 }; साथ है कर सकते हैं।

यह दोनों तरफ से लाभ हो सकता है या नहीं।

उदाहरण

int baz(int const* ptr) { 
    if (ptr) return 7; return -1; 
} 
int foo(int x) 
{ 
    // enum : int { bar = 456 }; 
    constexpr int bar = 456; 
    return x + baz(&bar); 
} 

enum संस्करण संकलन नहीं है के लिए, constexpr int करता। एक constexpr int एक लाभार्थी हो सकता है, एक गणक (सूचीबद्ध एनम स्थिरांक में से एक) नहीं कर सकता है।

enum मान वास्तव में int नहीं हैं, जबकि constexpr int वास्तव में int है। इससे कोई फर्क नहीं पड़ता कि आप इसे

template<class T> 
void test(T) { 
    static_assert(std::is_same<T,int>::value); 
} 

पास पास करेंगे; दूसरा नहीं होगा।

फिर से, यह टोकन का उपयोग करने के तरीके के आधार पर यह एक लाभ, हानि या एक अर्थहीन quirk हो सकता है।

+0

मुझे पता है कि ओडीआर क्या है, लेकिन मुझे यकीन नहीं है कि आप "ओडीआर-अस्तित्व" से क्या मतलब रखते हैं। जैसा कि enum संस्करण संकलित नहीं है - AFAIK वास्तव में इसे संकलित नहीं करना चाहिए। जैसा कि आपने कहा था, मैं एक 'int' वैरिएबल नाम बार नहीं चाहता हूं, केवल एक मान जो संकलन समय पर' int 'की तरह व्यवहार करता है। मैं वास्तव में थोड़ा आश्चर्यचकित हूं कि दूसरा संस्करण संकलित करता है - इसका मतलब है कि बार में आवंटित स्मृति में स्थान होना चाहिए। – einpoklum

+2

यदि संकलक यह आवश्यक है तो इसमें केवल आवंटित स्मृति में स्थान होगा। यदि आप पता नहीं ले रहे हैं, तो यह असंभव है; भले ही कंपाइलर कहीं भी नंबर स्टोर करना चाहता था, शायद यह एक रजिस्टर का उपयोग करेगा, और यह आमतौर पर मूल्य को स्टोर नहीं करना चाहता। एक 'constexpr int', ज्यादातर मामलों में, एक मान है जो संकलन समय पर केवल मौजूद है। –

+0

@inpok ओडीआर का मतलब है कि कुछ ऐसा किया गया था कि चर के * पहचान * न केवल मूल्य की आवश्यकता है। एक 'constexpr' मान का एक मान होता है जिसे संकलित समय पर गणना की जा सकती है, लेकिन यह * पहचान भी हो सकती है; एक enum मूल्य पहचान नहीं हो सकता है। पहचान का अस्तित्व "वास्तव में स्मृति में मौजूद" जैसा है लेकिन काफी नहीं; कभी-कभी पहचान वाली चीजें उनकी स्मृति को अनुकूलित कर सकती हैं। "पहचान" मानक से एक शब्द नहीं है, बस इसे समझाने का प्रयास है। – Yakk

1

वन-लाइनर (लेकिन यह मेरी अपनी ले है) @ Yakk के आधार पर:

enum आधारित स्थिरांक का उपयोग कर आवश्यक हो सकता है अगर आप अपने लगातार रन टाइम पर एक "चर" के रूप में मौजूद करने की अनुमति नहीं दे सकते। एक enum के साथ, आप जो भी करते हैं उसके बावजूद - इसमें कोई पता नहीं होगा और कोई स्मृति स्थान नहीं लिया जाएगा (और न केवल संकलक अनुकूलन के कारण जो हो सकता है या नहीं हो सकता है)।

अन्य मामलों में एक दूसरे को पसंद करने के लिए एक अनिवार्य कारण प्रतीत नहीं होता है।

+0

कोई "परिवर्तनीय" स्थिरता के लिए जगह लेना नहीं है जो ओडीआर-प्रयुक्त नहीं है। यह अनुकूलन पर निर्भर नहीं है, यह भाषा द्वारा बहुत अधिक गारंटीकृत है (मानक वास्तव में "स्मृति स्थान" के बारे में बात नहीं करता है, इसलिए यह वास्तव में उन शब्दों में नहीं कहता है)। –

+0

बर्बाद स्थान के बारे में एक गुमराह (आईएमएचओ) चिंता के कारण आपके कोड को वर्गीकृत करना और नए प्रकारों (enum) का आविष्कार करना गलत समस्या पर ध्यान केंद्रित कर रहा है। [संबंधित नामित स्थिरांक के सेट का प्रतिनिधित्व करने के लिए गणनाओं का उपयोग करें] (https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Renum-set), और [अनाम नामों से बचें] (https: // github। com/isocpp/cppCoreGuidelines/blob/master/CppCoreGuidelines.md # Renum-unnamed) ("इस तरह का कोड पूर्णांक स्थिरांक निर्दिष्ट करने के सुविधाजनक वैकल्पिक तरीके से पहले कोड में असामान्य नहीं है। वैकल्पिक: इसके बजाय constexpr मानों का उपयोग करें।") –

+1

@ जोनाथन वाक्ली: गुमराह किया गया है या नहीं, इसका सवाल संदर्भ पर निर्भर करता है। कोई व्यक्ति 'constexpr' फ़ील्ड के लिए स्थान आवंटन को ट्रिगर कर सकता है, और अलग-अलग मेमोरी लेआउट अन्यत्र संकलित कोड के साथ असंगतता का कारण बन सकता है। – einpoklum

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

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