2012-09-05 14 views
7

यह देखने के लिए कि यह कैसे काम करता है, मैंने हेडर type_traits में std::common_type के libstdC++ कार्यान्वयन को देखा। मुझे यह मानना ​​है कि मैं वास्तव में समझ नहीं पा रहा हूं कि यह कैसे काम करता है। यहां यह है:std :: common_type कार्यान्वयन

/// common_type 
template<typename... _Tp> 
    struct common_type; 

template<typename _Tp> 
    struct common_type<_Tp> 
    { typedef _Tp type; }; 

template<typename _Tp, typename _Up> 
    struct common_type<_Tp, _Up> 
    { typedef decltype(true ? declval<_Tp>() : declval<_Up>()) type; }; 

template<typename _Tp, typename _Up, typename... _Vp> 
    struct common_type<_Tp, _Up, _Vp...> 
    { 
     typedef typename 
     common_type<typename common_type<_Tp, _Up>::type, _Vp...>::type type; 
    }; 

मैं समझता हूं कि पहली, दूसरी और चौथी घोषणाएं कैसे काम करती हैं। हालांकि, मैं समझ नहीं पा रहा हूं कि तीसरी घोषणा कैसे काम करती है। क्या कोई यहां इस्तेमाल की गई तंत्र को समझाने की कोशिश कर सकता है?

उत्तर

8

सबसे पहले, std::declval<T>()T प्रकार का आर-मान उत्पन्न करता है। मूल्य के साथ कुछ भी करने की कोशिश करना असफल हो जाएगा, इसलिए इसका उपयोग केवल एक अपरिचित संदर्भ में किया जा सकता है। इसके बाद, टर्नरी ऑपरेटर अपने प्रकार को दोनों तर्कों के लिए सबसे विशिष्ट प्रकार के रूप में कम करता है (यदि ऐसा कोई प्रकार नहीं है, तो यह विफल हो जाता है)। तो, अभिव्यक्ति

true? declval<T0>(): declval<T1>() 

के प्रकार T0 और T1 के सबसे विशेष आम प्रकार है। यह सब कुछ इस अभिव्यक्ति को एक प्रकार में बदलने और यह सुनिश्चित करने के लिए है कि इसका मूल्यांकन नहीं किया जाता है। decltype(expr) बस यह करता है। जाहिर है, तर्क के मांस के दो तर्क संस्करण: दूसरों वहाँ कोने मामले (एक तर्क) से निपटने के लिए और दो तर्क संस्करण लाभ उठाने के लिए मनमाने ढंग से प्रकार के आम प्रकार की उपज के लिए कर रहे हैं।

3

तीसरा संस्करण सामान्य प्रकार निर्धारित करने के लिए सशर्त ऑपरेटर का उपयोग करता है। इसके नियमों को मानक की धारा 5.16 में काफी लंबाई में वर्णित किया गया है, इसलिए मुझे यकीन नहीं है कि मुझे उन्हें यहां कॉपी करना चाहिए।

सीधे शब्दों में कहें, अभिव्यक्ति:

boolean-expression ? second-operand : third-operand 

दूसरे और तीसरे ऑपरेंड के एक "आम प्रकार" है, अगर इस तरह से मौजूद है। decltype विनिर्देशक को अभिव्यक्ति को "प्रकार" को एक प्रकार-विनिर्देशक में परिवर्तित करने के लिए उपयोग किया जाता है।

+3

+1, टर्नरी ऑपरेटर सहित * जादू * पर एक अच्छा पठन: [सशर्त प्यार: फोरएच रेडक्स] (http://www.artima.com/cppsource/foreach.html) –

+0

ठीक है, मुझे लगता है कि मुझे अंत में मिला चाल। तो यह इस तथ्य पर निर्भर करता है कि टर्नरी ऑपरेटर अपने ऑपरेटरों के आधार पर अपने रिटर्न प्रकार को कम करता है। यह उस बारे में नहीं सोचा था। धन्यवाद! – Morwenn

1

लांग कहानी कम: decltype C++ कम्पाइलर इसके लिए निकटतम पूर्वज प्रकार का निर्धारण कर रही है।

तृतीयक ऑपरेटर के दो संभावित भाव के निकटतम पूर्वज के परिणामस्वरूप स्थिर प्रकार है।

उदा:

बी से एक विरासत

एक्स विरासत में वाई बी

<expression> ? <expression with static type A> : <expression with static type X> 
    = <expression with static type B> // this is how the C++ parser sees it 

से विरासत से यह कैसे काम करता है सी ++ भाषा है। Decltype बस टाइपिफ़ को उस अभिव्यक्ति के परिणाम का स्थिर प्रकार बनाता है (जो भी प्रकार सी ++ संकलक इसे निर्धारित करता है)

+0

इस मामले * पूर्वज * के उपयोग में और उदाहरण में वंशानुक्रम का उपयोग थोड़ा भ्रामक है। यकीन है कि यह है कि करता है, लेकिन यह बहुत अधिक करता है, तो प्रकारों में से एक है दूसरे के लिए * परिवर्तनीय *, यह 'उदाहरण के लिए, दूसरे प्रकार का चयन करेंगे (सच? 1, 1.)' 'लिखते ही double' है' int' परिवर्तनीय है डबल, हालांकि कोई * पूर्वज * या * विरासत * नहीं है। –

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