2011-10-03 10 views
14

से अलग है I सी ++ मानक आईएसओ/आईईसी 14882-03 14.6.1/9 में कोड को एक्सकोड 4.1 और विजुअल स्टूडियो 2008 पर कोड का परीक्षण करता है। दो कंपाइलर मानक के अपेक्षित परिणाम से अलग हैं।कक्षा टेम्पलेट में नाम समाधान का वास्तविक परिणाम सी ++ 03 मानक

कोड नीचे चिपकाया गया है।

#include <stdio.h> 
#include <iostream> 
using namespace std; 

void f(char); 

template <class T > void g(T t) 
{ 
    f(1); 
    f(T(1)); 
    f(t); 
} 

void f(int); 
void h() 
{ 
    g(2); 
    g('a'); 
} 

void f(int) 
{ 
    cout << "f int" << endl; 
} 


void f(char) 
{ 
    cout << "f char" << endl; 
} 


int main() { 
    h(); 
    return 0; 
} 

मानक के विवरण के रूप में। अपेक्षित आउटपुट

f char 
f int 
f int 
f char 
f char 
f char 

एक्सकोड 4.1 पर कोड बनाएं और चलाएं। आउटपुट नीचे जैसा है। बिल्ड सेटिंग्स में, मैंने ऐप्पल एलएलवीएम कंपाइलर 2.1, जीसीसी 4.2 और एलएलवीएम जीसीसी 4.2 के लिए "सी/सी ++/ऑब्जेक्ट-सी के लिए कंपाइलर" को बदलने की कोशिश की। आउटपुट एक ही हैं।

f char 
f char 
f char 
f char 
f char 
f char 

माइक्रोसॉफ्ट विजुअल स्टूडियो 2008 पर कोड बनाएं और चलाएं। आउटपुट नीचे जैसा है।

f int 
f int 
f int 
f int 
f char 
f char 

मानक के विवरण (14.6.1/9) नीचे चिपकाया गया है।

यदि कोई नाम किसी टेम्पलेट-पैरामीटर (जैसा कि 14.6.2 में परिभाषित किया गया है) पर निर्भर नहीं है, तो उस नाम के लिए घोषणा (या घोषणापत्रों का सेट) उस बिंदु पर होगा जहां नाम प्रकट होता है टेम्पलेट परिभाषा; नाम उस बिंदु पर मिलने वाली घोषणा (या घोषणाओं) से जुड़ा हुआ है और यह बाध्यकारी तत्कालता के बिंदु पर दिखाई देने वाली घोषणाओं से प्रभावित नहीं है। [उदाहरण:

void f(char); 
template<class T> void g(T t) 
{ 
f(1); // f(char) 
f(T(1)); // dependent 
f(t); // dependent 
dd++; // not dependent 
} 
void f(int); 
double dd; 
void h() 
{ 
// error: declaration for dd not found 
g(2); // will cause one call of f(char) followed // by two calls of f(int) 
g(’a’); // will cause three calls of f(char) 

अंत उदाहरण]

कोड compilers करने के लिए अच्छी तरह से बनाई है, लेकिन आउटपुट अलग हैं। इस कोड को विभिन्न प्लेटफॉर्म पर पोर्ट करना बहुत खतरनाक होगा।

क्या किसी के पास पृष्ठभूमि है क्यों ये कंपाइलर्स मानक का पालन नहीं करते हैं?

संपादित 10/11/2011

प्रति http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#197 पर, मानक में उदाहरण गलत है। मैं क्लैंग और जीसीसी पर नीचे दिए गए कोड का परीक्षण करता हूं।

#include <stdio.h> 
#include <iostream> 
using namespace std; 

void f(char); 

template <class T > void g(T t) 
{ 
    f(1); 
    f(T(1)); 
    f(t); 
} 

enum E{ e }; 

void f(E); 
void h() 
{ 
    g(e); 
    g('a'); 
} 

void f(E) 
{ 
    cout << "f E" << endl; 
} 

void f(char) 
{ 
    cout << "f char" << endl; 
} 

int main() { 
    h(); 
    return 0; 
} 

अपेक्षित आउटपुट।

f char 
f E 
f E 
f char 
f char 
f char 

धन्यवाद,

जेफरी

+2

+1 पहले पहले प्रश्न –

+0

दिलचस्प बात यह है कि क्लैंग 2.9 में जीसीसी की तुलना में एक ही समस्या है। –

उत्तर

3

जैसा कि पहले उदाहरण में उल्लेख किया गया है, यह दो चरण नाम लुकअप का एक उदाहरण है, जो जीसीसी और क्लैंग दोनों लागू होते हैं लेकिन एमएसवीसी नहीं करता है। और इस मामले में, जीसीसी और क्लैंग दोनों सही हैं: यह वास्तव में मानक है जो गलत है, जैसा कि सी ++ core defect report #197 में उल्लेख किया गया है। सी ++ 11 मानक में एक अलग उदाहरण है।

यह most common problems में से एक है, हम देखते हैं कि एमएसवीसी (जो कभी दो चरण नाम लुकअप लागू नहीं किया गया) या जीसीसी से क्लैंग को कोड पोर्ट करते समय (जो हाल ही में दो चरण नाम लुकअप को समान रूप से लागू नहीं किया गया था)।

2

मैं नहीं जानता कि क्या आप सिवाय इसके कि मैं तुम्हारे साथ सहमत होंगे कि यह ग़लत व्यवहार है बताने के लिए।

मुझे लगता है कि शायद यह हो रहा है कि एमएसवीसी के मामले में, कंपाइलर बाद में परिभाषित फ़ंक्शन के ज्ञान के साथ समाप्त होने की लागत पर एक अतिरिक्त पास को अनुकूलित कर रहा है जिसे गैर-मामले के मामले में उपयोग नहीं किया जाना चाहिए -टेम्प्लेट कॉल मुझे कबूल करना होगा, मुझे नहीं पता कि जीसीसी/एलएलवीएम उनके द्वारा किए गए परिणामों के साथ कैसे समाप्त होगा, क्योंकि परिणाम आप अपवाद के रूप में अपेक्षा करेंगे और नियम नहीं।

मुझे लगता है कि मैं इसे http://bugreport.apple.com/ और http://connect.microsoft.com/ पर एक बग के रूप में दर्ज करूंगा और देख सकता हूं कि वे क्या कहते हैं?

+0

धन्यवाद, महमूद। यदि कोई टिप्पणी है तो कृपया मुझे अपडेट रखें। – Jeffrey

+1

@ जेफरी: मुझे लगता है कि वह सुझाव दे रहा था कि आप बग फाइल करें। :) –

+0

जी ++ 4.6.1 एक्सकोड के समान व्यवहार दिखाता है (जिसमें तुलनात्मक रूप से प्राचीन जी ++ 4.2 है), इसलिए कृपया http://gcc.gnu.org/bugzilla/ पर एक बग रिपोर्ट दर्ज करें। – zwol

5

आप जो भी चल रहे हैं वह यह तथ्य है कि विजुअल स्टूडियो two-phase lookup लागू नहीं करता है। जब आप टेम्पलेट को तुरंत चालू करते हैं तो वे केवल वास्तविक नाम को देखते हैं।

और माइक्रोसॉफ्ट ने इस बिंदु पर काफी निर्णय लिया है कि वे दो चरण के लुकअप का समर्थन करने में रूचि नहीं रखते हैं।

+0

एमएसवीसी एक खोया कारण है, हालांकि मुझे हैरान है कि जीसीसी और क्लैंग को यह गलत लगेगा। –

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