2009-12-08 12 views
6

इस कोड पर विचार करें:सरणी क्षय

#include <iostream> 

template<typename T> 
void f(T x) { 
    std::cout << sizeof(T) << '\n'; 
} 

int main() 
{ 
    int array[27]; 
    f(array); 
    f<decltype(array)>(array); 
} 

संपादक का ध्यान दें: मूल कोड का इस्तेमाल किया typeof(array), हालांकि कि एक जीसीसी विस्तार है।

यह

8 (or 4) 
108 

प्रिंट होगा पहले मामले में, सरणी स्पष्ट रूप से एक सूचक को decays और टी int* हो जाता है। दूसरे मामले में, टी को int[27] पर मजबूर किया गया है। क्षय/प्रतिस्थापन कार्यान्वयन का आदेश परिभाषित किया गया है? क्या int[27] पर बल को मजबूर करने का एक और शानदार तरीका है? Std :: वेक्टर का उपयोग करने के अलावा?

+3

आपको सी ++ कंपाइलर कहां मिला जहां 'sizeof (int) == 1'? मुझे दूसरी कॉल के लिए 108 मिलते हैं। –

+0

हां, ज़ाहिर है कि जीसीसी पहले से ही 4 बाइट इन्स तक चली गई है ;-) मैंने टेस्टकेस उत्पन्न करते समय एक बग पेश किया है। – hirschhornsalz

+0

मैं दूसरी कॉल संकलन आश्चर्यचकित हूं। आप सी ++ में मान द्वारा सरणी पास नहीं कर सकते हैं। [संपादित करें: आह, 'टी' में सरणी प्रकार है, लेकिन 'sizeof (x)' अभी भी 8 या 4 आउटपुट करेगा। कभी भी ध्यान न दें। :)] –

उत्तर

9

पैरामीटर

template<typename T> void f(const T& x) 
{ 
    std::cout << sizeof(T); 
} 

जिस स्थिति में सरणी प्रकार क्षय नहीं होगा के लिए संदर्भ प्रकार का उपयोग करें।

इसी तरह, आप भी क्षय f के अपने मूल संस्करण में यदि आप स्पष्ट रूप से अपने मूल कोड नमूने में एक संदर्भ करने वाली सरणी प्रकार के रूप में टेम्पलेट agument T निर्दिष्ट

f<int (&)[27]>(array); 

, तर्क T मजबूर कर रोका जा सकता है typeof या स्पष्ट रूप से प्रकार निर्दिष्ट करके सरणी प्रकार (यानी गैर-संदर्भ सरणी प्रकार) रखने के लिए, सरणी प्रकार क्षय को रोक नहीं पाएगा। जबकि T स्वयं सरणी प्रकार (जैसा कि आपने देखा है) के लिए खड़ा होगा, पैरामीटर x अभी भी एक सूचक के रूप में घोषित किया जाएगा और sizeof x अभी भी सूचक आकार का मूल्यांकन करेगा।

+0

हां, लेकिन मैं sizeof (टी) का उपयोग कर रहा हूँ। वैसे भी, तेज़ उत्तर के लिए धन्यवाद :-) – hirschhornsalz

1

आपके उपयोग के मामले के आधार पर, आपको लगता है कि using references को हल करने के कर सकते हैं:

template<typename T> 
void f(const T& x) { 
    std::cout << sizeof(T); 
} 

char a[27]; 
f(a); 

कि 27 प्रिंट, के रूप में वांछित।

+0

देखें शायद किसी कॉन्स्ट-रेफरेंस का उपयोग करना चाहिए, क्योंकि आप टी – GManNickG

+0

को संशोधित नहीं कर रहे हैं, ठीक है, ओपीएस कोड में आवश्यक न्यूनतम परिवर्तन किए गए हैं। –

1

तुम भी निम्नलिखित की तरह टेम्पलेट का उपयोग कर सकते हैं:

template <typename T, std::size_t N> 
inline std::size_t number_of_elements(T (&ary)[N]) { 
    return N; 
} 

इस छोटे चाल त्रुटियों संकलन अगर समारोह एक गैर सरणी प्रकार पर प्रयोग किया जाता है का कारण होगा।

2

इस कोड का व्यवहार सी ++ 14 [temp.deduct द्वारा समझाया गया है।फोन]:

एक समारोह कॉल

खाका तर्क कटौती प्रत्येक कार्य टेम्पलेट पैरामीटर प्रकार की तुलना द्वारा किया जाता है से टेम्पलेट तर्क बात का अनुमान लगाना (यह P कॉल) कॉल की इसी तर्क के प्रकार के साथ (यह A) कहते हैं तो नीचे नीचे

वर्णित है और के रूप में:

तो P एक संदर्भ प्रकार नहीं है:

  • तो A एक सरणी प्रकार, सूचक प्रकार सरणी-टू-सूचक मानक रूपांतरण (4.2) द्वारा निर्मित है प्रकार कटौती के लिए A के स्थान पर प्रयोग किया जाता है;

कॉल f(array); के लिए, हम A = int[27] है। A एक सरणी प्रकार है। इसलिए इस अंतिम बुलेट बिंदु के मुताबिक, Tint * है।

हम क्वालीफायर से देख सकते हैं "अगर P एक संदर्भ प्रकार नहीं है" तो यह व्यवहार शायद P एक संदर्भ प्रकार बनाकर बचा जा सकता है। कोड के लिए:

template<typename T, size_t N> 
void f(T (&x)[N]) 

प्रतीक P मतलब है T(&)[N] है, जो एक संदर्भ प्रकार है; और यह पता चला है कि यहां कोई रूपांतरण लागू नहीं है। T को int पर xint(&)[N] के प्रकार के साथ घटाया गया है।


ध्यान दें कि यह केवल फ़ंक्शन टेम्पलेट्स पर लागू होता है जहां तर्क तर्क से लिया जाता है। व्यवहार स्पष्ट रूप से प्रदान किए गए फ़ंक्शन टेम्पलेट पैरामीटर और क्लास टेम्पलेट्स के लिए विनिर्देश के अलग-अलग हिस्सों द्वारा कवर किया गया है।

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