2016-03-05 12 views
8

निम्नलिखित टुकड़ा पर विचार करें:समारोह टेम्पलेट में आश्रित नाम लुकअप: बजना को खारिज कर दिया, जीसीसी स्वीकार करता

struct X { }; 

namespace foo { 
    template <class T> 
    void bar() { T{} < T{}; } 

    void operator<(const X&, const X&) {} 
} 

int main() { 
    foo::bar<X>(); 
} 

बजना इस कोड को खारिज कर दिया, जीसीसी यह स्वीकार करता है। क्या यह एक जीसीसी बग है या यह एक क्लैंग बग है?

+0

मुझे नहीं लगता कि यह एक बग कैसा है क्योंकि टाइप 'टी' किसी भी प्रकार का संदर्भ दे सकता है। यदि वह प्रकार 'टी' अधिभारित नहीं करता है या' <'ऑपरेटर का समर्थन नहीं करता है तो 'बार' फ़ंक्शन विफल हो जाएगा। चूंकि आपने '<' ऑपरेटर को अधिभारित कर लिया है, यह सब अच्छा है। मुझे लगता है कि यह सब नीचे चला जाता है कि कैसे कंपेलर कोड पढ़ते हैं, लेकिन अर्थशास्त्र-वार यह बग-प्रवण नहीं है। – Poriferous

+0

@ प्रायोजक जो कोई समझ नहीं आता है। प्रश्न यह है कि 'bar()' के प्रकार का सही व्यवहार किस प्रकार 'टी' के लिए है जिसका 'ऑपरेटर <'नहीं है। सही व्यवहार या तो है: "हां, यह 'बार :: ऑपरेटर <' "(इस मामले में, क्लैंग में एक बग है) या" कोड खराब बना हुआ है "(इस मामले में, जीसीसी में एक बग है)। – Barry

+0

इसका कोई मतलब नहीं है क्योंकि 'बार' एक फ़ंक्शन है और इसमें कोई सदस्य नहीं है' ऑपरेटर <'। चूंकि आपने 'एक्स' के लिए 'ऑपरेटर <' को परिभाषित किया है, इसलिए मैं वास्तव में नहीं देखता कि समस्या क्या है। भले ही ऑपरेटर ओवरलोड को 'एक्स'' में एम्बेडेड किया गया हो, फिर भी कोड को सही ढंग से संकलित करना चाहिए। निष्पक्ष होने के लिए, यह क्लैंग है जिसमें बग है क्योंकि ऐसा लगता है कि एक प्रकार क्या है। मेरा मतलब है, क्या आपने 'foo :: bar ()' को 'foo :: bar ()' जैसे कुछ के साथ बदलने की कोशिश की है और देखें कि क्लैंग उस कोड को भी अस्वीकार करता है या नहीं? – Poriferous

उत्तर

5

जीसीसी गलत है क्लैंग सही है। तथ्य यह है कि जीसीसी ने आपके द्वारा दिखाए गए अमान्य कोड को निगल लिया है, जिसका भी CLANG के संगतता पृष्ठ here में उल्लेख किया गया है।

अयोग्य नाम निम्नलिखित तरीकों से देखे जाते हैं।

  1. कंपाइलर उस दायरे में अयोग्य लुकअप आयोजित करता है जहां नाम लिखा गया था। टेम्पलेट के लिए, इसका अर्थ यह है कि लुकअप उस बिंदु पर किया जाता है जहां टेम्पलेट परिभाषित किया गया है, जहां यह तत्काल नहीं है। चूंकि operator< इस बिंदु पर अभी तक घोषित नहीं किया गया है, अयोग्य लुकअप इसे नहीं मिलेगा।
  2. यदि नाम को फ़ंक्शन की तरह कहा जाता है, तो संकलक तर्क-निर्भर लुकअप (एडीएल) भी करता है। (कभी-कभी अयोग्य लुकअप एडीएल को दबा सकता है; अधिक जानकारी के लिए [basic.lookup.argdep] अनुच्छेद 3 देखें।) एडीएल में, कंपाइलर कॉल के सभी तर्कों के प्रकारों को देखता है। जब इसे कक्षा के प्रकार मिलते हैं, तो वह उस वर्ग के नामस्थान में नाम देखता है; नतीजा यह है कि उन नामस्थानों में यह सभी घोषणाएं मिलती हैं, साथ ही अयोग्य लुकअप से घोषणाएं भी होती हैं। हालांकि, संकलक एडीएल नहीं करता है जब तक कि यह सभी तर्क प्रकारों को जानता न हो।
6

मेरा मानना ​​है कि यह एक जीसीसी बग है, जिसे 70099 के रूप में दायर किया गया है। [Temp.dep.res] से:

निर्भर नामों को हल करने के लिए, निम्न स्रोतों से नाम माना जाता है:
(1.1) - घोषणा कि टेम्पलेट की परिभाषा के बिंदु पर दिखाई दे रहे हैं।
(1.2) - तत्काल संदर्भ (14.6.4.1) और परिभाषा संदर्भ से दोनों फ़ंक्शन तर्कों के प्रकार से जुड़े नामस्थानों से घोषणाएं।

foo::operator<() टेम्पलेट की परिभाषा के बिंदु पर दिखाई नहीं देता है, और समारोह तर्क से एक संबद्ध नाम स्थान में नहीं है (X के जुड़े नाम स्थान सिर्फ वैश्विक नामस्थान :: है)। तो मुझे लगता है कि जीसीसी foo::operator< ढूंढना गलत है और कोड को अस्वीकार करने के लिए क्लैंग सही है।

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