2014-10-17 6 views
15

कोड की निम्न बिट VS2008 और जीसीसी 4.8.2 में संकलितटाइपपीफ फू <> फू संकलित करता है लेकिन क्या यह मान्य है?

template<typename T=void> 
struct Foo 
{ 
}; 

// typedef Foo<> Foo; // Does *NOT* compile 

int main() 
{ 
    typedef Foo<> Foo; 
    Foo f1; 

    // Foo<char> f2;  // Does *NOT* compile 
    //::Foo<char> f3; // COMPILES 
} 

यह वैध है?

+1

आप टेम्पलेट में डिफ़ॉल्ट तर्क प्रदान कर रहे हैं। यह पूरी तरह से मान्य है। –

+2

@ कैप्टन: लेकिन इस तथ्य के बारे में क्या है कि वे दोनों 'फू' नामक हैं? – Cameron

उत्तर

17

प्रति सी ++ 11 3.3.10/1 के रूप में:

एक नाम पर है कि एक ही नाम के एक स्पष्ट घोषणा से छिपा हो सकता है घोंसला घोषित क्षेत्र या कक्षा व्युत्पन्न।

(जोर मेरा)

है यही कारण है कि टेम्पलेट का नाम Foomain() अंदर typedef नाम Foo द्वारा छिपा हो सकता है (एक अलग गुंजाइश), लेकिन एक ही दायरे में के रूप में टेम्पलेट का नाम घोषित किया जाता है नहीं।

क्यों यह इसी तरह के मामले में कानूनी है करने के लिए के रूप में:

struct Foo 
{ 
}; 

typedef Foo Foo; // *DOES* compile 

स्पष्ट 7.1.3/3 द्वारा अनुमति दी है कि:

किसी दिए गए गैर-वर्ग दायरे में, एक typedef विनिर्देशक हो सकता है उस स्कोप में घोषित किसी भी प्रकार के नाम को फिर से परिभाषित करने के लिए उपयोग किया जाता है, जिस प्रकार से यह पहले से संदर्भित होता है।

+4

+1 spec उद्धृत करने के लिए +1! –

+1

3.3.1 [basic.scope.declarative]/p4 भी प्रासंगिक है। –

11

हाँ, यह वैध है, एक ही कारण है कि यह वैध है के लिए:

struct Foo { }; 

namespace bar { 
    struct Foo { }; 
} 

तुम सिर्फ एक अलग दायरे में नाम अधिलेखित कर रहे हैं। मुख्य के अंदर, आप अभी भी कुछ इस तरह कर सकते हैं:

::Foo<int> f2; 
+0

आह, टाइपनाम शेडिंग। कितनी स्वादिष्ट स्नीकी: ओ – Cameron

+0

मुझे लगता है कि यह उत्तर सही नहीं है - एक टेम्पलेट फू एक टाइपेडफ (एक नामस्थान में) द्वारा प्रतिस्थापित किया गया है –

+0

@ डाइटर लुकिंग क्यों? मैं मुख्य रूप से आसानी से 'int foo = 7' बना सकता हूं; यह सिर्फ एक नाम है। – Barry

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