2012-08-29 16 views
18

जब मैं g++typedef परिवर्तन अर्थ

template<class T> 
class A 
{}; 

template<class T> 
class B 
{ 
    public: 
     typedef A<T> A; 
}; 

साथ निम्नलिखित स्निपेट संकलन संकलक मुझे,

error: declaration of ‘typedef class A<T> B<T>::A’ 
error: changes meaning of ‘A’ from ‘class A<T>’ 

बताता है दूसरी ओर अगर मैं typedef

को
typedef ::A<T> A; 

बदल सब कुछ g++ के साथ ठीक संकलित करता है। Clang ++ 3.1 किसी भी तरह से परवाह नहीं करता है।

ऐसा क्यों हो रहा है? और दूसरा व्यवहार मानक है?

+1

यह चेतावनी स्तर होना चाहिए जो डिफ़ॉल्ट रूप से इसे एक त्रुटि के रूप में दिखाता है। जैसा कि आपके पास एक फ़ंक्शन अनुपलब्ध रिटर्न हो सकता है और एक त्रुटि या चेतावनी के रूप में रिपोर्ट किया जा सकता है। आम तौर पर, मैं ए के रूप में घोषित प्रकार ए से बचने से बचूंगा। यह बाद में भ्रमित हो जाएगा। – Grzegorz

+0

मुझे नहीं पता कि मानक क्या कहता है, लेकिन मुझे खुशी है कि g ++ शिकायत करता है ... यह सिर्फ मूर्ख है। –

+0

मुझे लगता है कि यह न तो मूर्ख है, न ही भ्रमित है। मैं अक्सर इस समस्या में भाग लेता हूं। त्रुटि रूपांतरण के लिए चेतावनी के लिए, मैं किसी भी झंडे को g ++ नहीं दे रहा हूं, डिफ़ॉल्ट रूप से त्रुटियों में यह कौन सी चेतावनियां परिवर्तित होती है? – foxcub

उत्तर

10

जी ++ मानक के अनुरूप और अनुरूप है। से [3.3.7/1]:

एक नाम एन एक वर्ग एस में इस्तेमाल अपने संदर्भ में एक ही घोषणा का उल्लेख होगा और के एस नहीं नैदानिक ​​पूरा दायरे में जब पुनः आकलन की आवश्यकता है इस नियम के उल्लंघन के लिए।

typedef से पहले, A::A करने के लिए भेजा है, तथापि typedef का उपयोग करके, आप अब A typedef जो निषिद्ध है का उल्लेख करते हैं। हालांकि, no diagnostic is required के बाद से, क्लैंग भी मानक अनुरूप है।

jogojapan's comment इस नियम का कारण बताता है। अपने कोड के लिए निम्न परिवर्तन लें:

template<class T> 
class A 
{}; 

template<class T> 
class B 
{ 
    public: 
     A a; // <-- What "A" is this referring to? 
     typedef  A<T>   A; 
}; 
क्योंकि कैसे वर्ग गुंजाइश काम करता है की

, A a; अस्पष्ट हो जाता है।

+0

दूसरे फॉर्म के बारे में कैसे? क्या यह भी एक त्रुटि है, और जी ++ बस इसकी रिपोर्ट नहीं करता है? – foxcub

+3

@ फॉक्सक्यूब: दूसरे रूप में आप 'ए' का जिक्र नहीं कर रहे हैं, आप' :: ए' का जिक्र कर रहे हैं। दूसरा फॉर्म सही है। –

+0

@ फॉक्सक्लब: दूसरा फॉर्म ठीक है (केविन बल्लार्ड बताते हैं), क्योंकि 'ए' का अर्थ नहीं बदलता है। –

1

मैं संकलन में जीसीसी के उचित रूप में अजीब व्यवहार के बारे में जेसी के जवाब देने के लिए जोड़ देगा:

typedef A<T> A; 

बनाम

typedef ::A<T> A; 

यह भी बयान के रूप में अच्छी के रूप का उपयोग कर लागू होता है:

using A = A<T>; 
using A = ::A<T>; 

जीसीसी के भीतर क्या हो रहा है, यह है कि टाइपिफ़/यू के संकलन के दौरान बी :: ए घोषित करने का बयान गाते हैं कि प्रतीक बी :: ए एक वैध उम्मीदवार बनता है जिसका उपयोग कथन का उपयोग के भीतर होता है। अर्थात। using A = A<T>; या typedef A<T> A; कहकर जीसीसी ::A और B::AA<T> के लिए वैध उम्मीदवार दोनों को मानता है।

यह अजीब व्यवहार प्रतीत होता है क्योंकि आपके प्रश्न का तात्पर्य है, आप नए उपनाम ए को टाइपिफ़ के भीतर एक वैध उम्मीदवार बनने की उम्मीद नहीं करते हैं, लेकिन जैसा कि जेसी का जवाब भी कहता है, किसी वर्ग के भीतर घोषित कुछ भी अन्य सभी के लिए दृश्यमान हो जाता है कक्षा के अंदर - और इस मामले में स्पष्ट रूप से घोषणा भी। पुनरावर्ती प्रकार की परिभाषाओं को अनुमति देने के लिए इस तरह के व्यवहार को इस तरह कार्यान्वित किया जा सकता है।

जैसा समाधान आपने पाया है वह जीसीसी के लिए निर्दिष्ट करना है, जिसे आप टाइप किए गए संदर्भ में संदर्भित कर रहे हैं और फिर यह शिकायत नहीं करता है।

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