2015-01-22 11 views
10

निम्न C++ 11 कोड में, arraySize के लिए अंतिम कॉल संकलन त्रुटि का कारण बनता है। जाहिर है ऐसा इसलिए है क्योंकि y रनटाइम आकार का सरणी है, और arraySize टेम्पलेट पैरामीटर एन को y के लिए नहीं लिया जा सकता है। मुझे समझ में नहीं आता कि एक्स एक संकलित समय आकार का सरणी क्यों है, लेकिन वाई रनटाइम आकार समाप्त होता है। arraySize टेम्पलेट समारोह सीधे स्कॉट Meyers ' "प्रभावी आधुनिक सी ++" आइटम 1.सी ++: यह कॉन्स्टेक्सर संकलन समय स्थिर क्यों नहीं है

#include <cstddef> 

template<typename T, std::size_t N> 
constexpr std::size_t arraySize(T(&)[N]) noexcept { return N; } 

struct S 
{ 
    char c[10]; 
}; 

int main() 
{ 
    S s; 
    S* ps = &s; 

    char x[arraySize(s.c)]; 
    char y[arraySize(ps->c)]; // why is y a runtime sized array? 

    arraySize(x); 
    arraySize(y); // error !? 

    return 0; 
} 
+0

त्रुटि क्या है? –

+0

अच्छी तरह से मैं स्टंप हो गया हूं ... 'sc' और 'ps-> c' दोनों में एक ही प्रकार है, जैसा कि' टाइपिड (एससी) .name()' या 'टाइपिड (ps-> c) .name द्वारा छोड़ा गया है() ', यानी'जी ++ – vsoftco

+0

के लिए A10_c' उसे कुछ अतिरिक्त काला कर करने के लिए: यदि आप कर' arraySize() 'एक संदर्भ-टू-स्थिरांक, निम्नलिखित compiles पैरामीटर:' चार y [arraySize (decltype (ps-> ग) {})]; ' – Quentin

उत्तर

9

से लिया जाता है सी ++ में, त्रुटि arraySize(y) करने के लिए कॉल, लेकिन y खुद की घोषणा नहीं है।

सरणी घोषणा में सीमाएं "परिवर्तित निरंतर अभिव्यक्ति" होनी चाहिए।

यदि आपका कंपाइलर y की घोषणा स्वीकार करता है और बाद में आपको बताता है कि y रनटाइम बाउंड की एक सरणी है, तो यह सी ++ कंपाइलर नहीं है। सी ++ के किसी भी अनुमोदित संस्करण में न ही रनटाइम के कोई सरणी नहीं हैं, न ही वर्तमान ड्राफ्ट।

arraySize(s.c) और arraySize(ps->c) के बीच महत्वपूर्ण अंतर यह है कि ps->c(*ps).c रूप में ही है और * भिन्नता ऑपरेटर ps पर lvalue करने वाली rvalue रूपांतरण है, जो एक निरंतर अभिव्यक्ति नहीं है की आवश्यकता है (और न ही &s है, नीचे देखें)। शेष अभिव्यक्ति में लैवल्यू-टू-रावल्यू रूपांतरण शामिल नहीं है, सरणी लैवल्यू सीधे संदर्भ द्वारा बाध्य है।

एक निरंतर अभिव्यक्ति है या तो एक glvalue कोर निरंतर अभिव्यक्ति जिसका मूल्य (के रूप में नीचे वर्णित) एक इकाई एक निरंतर अभिव्यक्ति का एक अनुमति दी परिणाम है कि को संदर्भित करता है, या एक prvalue कोर निरंतर अभिव्यक्ति जिसका मूल्य एक वस्तु जहां है, उस वस्तु और उसके subobjects के लिए:

  • संदर्भ प्रकार से प्रत्येक गैर स्थैतिक डेटा सदस्य एक इकाई एक निरंतर अभिव्यक्ति का एक अनुमति दी परिणाम है कि करने के लिए संदर्भित करता है, और

  • मैं f ऑब्जेक्ट या सबोबजेक्ट पॉइंटर प्रकार का है, इसमें स्थिर स्टोरेज अवधि वाले ऑब्जेक्ट का पता, ऐसी ऑब्जेक्ट (5.7) के अंत में पता, फ़ंक्शन का पता, या शून्य सूचक मान होता है।

एक इकाई अगर यह स्थिर भंडारण अवधि के साथ एक वस्तु या तो एक अस्थायी वस्तु नहीं है या एक अस्थायी वस्तु जिसका मूल्य काफ़ी फाई तों ऊपर की कमी है, या यह एक है कि एक निरंतर अभिव्यक्ति का एक अनुमति दी परिणाम है फ़ंक्शन।

जाहिर ps स्वत: भंडारण अवधि के साथ एक वस्तु का पता होता है, तो यह constexpr घोषित नहीं किया जा सकता है। लेकिन सब कुछ, आपको लगता है कि चाहते हैं arraySize(s.c) पैरामीटर एक निरंतर अभिव्यक्ति या तो नहीं है, क्योंकि यह स्थिर भंडारण का एक उद्देश्य के लिए एक संदर्भ है और नहीं काम कर रहा है, तो आप S s; S* ps = &s;static S s; constexpr S* ps = &s; को

(बदल दूसरी ओर शुरू कर देना चाहिए अवधि)

+0

"अपने संकलक y की घोषणा को स्वीकार करता है और बाद में आपको बताता है कि y बाध्य क्रम की एक सरणी है, तो यह नहीं एक सी ++ संकलक है।" - यह हिस्सा सत्य नहीं है, एक अनुरूप कार्यान्वयन (कंपाइलर) को विस्तार से "स्वीकार" करने के लिए अनुमति दी गई है (यानी संकलन और/या निष्पादित) एक्सटेंशन के माध्यम से खराब गठित इनपुट, उदाहरण देखें। एन 4296 ड्राफ्ट में 1.4/8। इस मामले में डायग्नोस्टिक जारी करने के लिए कार्यान्वयन ** ** आवश्यक है, और जीसीसी और क्लैंग वेरिएबल-लम्बाई सरणी के लिए चेतावनी जारी करने में असफल हो जाते हैं जब तक कि आमंत्रण में विकल्प नहीं जोड़ा जाता है। –

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