2011-01-21 14 views
8

मैं ऑपरेटरों नाम स्थान my_namespace में वर्ग my_type के लिए घोषित की है।जीसीसी failes उपसर्ग नाम स्थान के साथ ऑपरेटर परिभाषा को संकलित करने के

namespace my_namespace { 
class my_type 
{ 
    friend std::ostream& operator << (std::ostream& out, my_type t); 
} 
} 

मैं कार्यान्वयन फ़ाइल में इन ऑपरेटरों को परिभाषित करने के कोशिश कर रहा हूँ, लेकिन जब मैं कि

std::ostream& my_namespace::operator << (std::ostream& out, my_type t) 
{ 
out << t; 
return out; 
} 

की तरह कुछ लिखने मैं

error: ... operator should have been declared inside 'my_namespace'

जब मैं इसे बदल त्रुटि संदेश मिलता है

namespace my_namespace { 
    std::ostream& operator << (std::ostream& out, my_type t) 
    { 
    out << t; 
    return out; 
    } 
} 
को

तो यह संकलित है, लेकिन मुझे समस्या को समझ में नहीं आता है। यह संकलन करने में विफल क्यों है? क्या उसके साथ सब ठीक है? मैं मानक के लिंक की सराहना करता हूं क्योंकि मुझे वास्तव में पता नहीं है कि खोजना क्या है।

file.h

#ifndef A_H 
#define A_H 

#include <iosfwd> 

namespace N 
{ 
class A 
{ 
    friend std::ostream& operator << (std::ostream& out, A& obj); 
}; 
} 

#endif 

file.cpp

#include "file.h" 
#include <iostream> 

std::ostream& N::operator << (std::ostream& out, N::A& obj) 
{ 
return out; 
} 

int main() {} 

यहाँ पूरा उदाहरण है जोड़ा। यह वीएस -2010 पर ठीक काम करता है, लेकिन जीसीसी 4.4.5 पर उपर्युक्त त्रुटि देता है।

हम्म ... हाँ, यह एक काम करता है

namespace N 
{ 
    class A 
    { 
     friend std::ostream& operator << (std::ostream& out, A& obj); 
    }; 
    std::ostream& operator << (std::ostream& out, A& obj); 
} 

मैं हमेशा दृश्यता कक्षा में दोस्त ऑपरेटर घोषित करने के मामले में सोच रहा था कि वर्ग की घोषणा के बाहर के रूप में एक ही बात है जोड़ा .. ऐसा लगता है कि यह नहीं है। धन्यवाद।

अग्रिम में बहुत धन्यवाद।

+0

जीसीसी में, '-फ्रीएंड-इंजेक्शन' विकल्प के साथ इसे संकलित करना सफल होगा। – user7610

उत्तर

9

त्रुटि संदेश यह सब कहते हैं, वास्तव में। आप कार्यान्वयन फ़ाइल में अपने समारोह परिभाषा रख सकते हैं, लेकिन आप पहले नाम स्थान में यह घोषणा करने के लिए की जरूरत है:

7.3.1.2/:

namespace my_namespace { 
    std::ostream& operator << (std::ostream& out, my_type t); 
} 

सी ++ मानक इस बारे में काफी स्पष्ट है 3:

हर नाम पहली बार एक नाम स्थान में घोषणा की है कि नाम स्थान का एक सदस्य है। यदि किसी गैर-स्थानीय वर्ग में किसी मित्र की घोषणा पहले कक्षा या घोषित करती है तो मित्र वर्ग या फ़ंक्शन आंतरिकतम नामस्थान नाम का सदस्य होता है। मित्र का नाम सरल नाम लुकअप द्वारा नहीं मिलता है जब तक कि नामस्थान स्कोप में मिलान की घोषणा नहीं की जाती है (या तो कक्षा घोषणा के पहले या बाद में दोस्ती दे रही है)। यदि किसी मित्र फ़ंक्शन को कॉल किया जाता है, तो इसका नाम नाम लुकअप द्वारा पाया जा सकता है जो फ़ंक्शन तर्कों (3.4.2) के प्रकार से जुड़े नामस्थानों और कक्षाओं के कार्यों को मानता है।किसी वर्ग की पूर्व घोषणा या किसी मित्र के रूप में घोषित फ़ंक्शन की तलाश करते समय, और जब मित्र वर्ग या फ़ंक्शन का नाम न तो एक योग्य नाम है और न ही टेम्पलेट-आईडी है, तो आंतरिक संलग्न नामस्थान स्कोप के बाहर स्कॉप्स पर विचार नहीं किया जाता है। ।

नीचे दिए गए लिंक इसे और अधिक बस डालता है, और कुछ उदाहरण जोड़ता है: http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr043.htm

तो मैं कहेंगे कि जीसीसी यहाँ गलत है। । प्रासंगिक वाक्य "होने के लिए मित्र का नाम सरल नाम देखने से नहीं पाया जाता है जब तक उससे मिलते-जुलते घोषणा (पहले या वर्ग घोषणा दोस्ती देने के बाद) कि नाम स्थान दायरे में प्रदान की जाती है लगता है।

+2

इसे पहले से ही नामस्थान में घोषित किया गया है (हेडर फ़ाइल में), है ना? – ledokol

+0

नहीं: "मित्र मित्र घोषणा में पहली बार पेश किए गए किसी मित्र समारोह या वर्ग का नाम दोस्ती देने वाले वर्ग के दायरे में नहीं है। किसी मित्र की घोषणा में पहली बार पेश किए गए फ़ंक्शन का नाम पहले गैर-वर्ग के दायरे के दायरे में है संलग्न वर्ग है। " (http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr043.htm) –

+0

... जिसका अर्थ है कि आप सही हैं ... बस एक सवाल: आपने वास्तव में स्रोत फ़ाइल में अपनी हेडर फ़ाइल शामिल की है, है ना? और कक्षा घोषणा के बंद होने के बाद '' '' '' था; –

1

घोषणा का उल्लेख अन्य नामों का एक सेट, और एक नया नाम प्रस्तुत करना; यह नया नाम किसी नामस्थान पहचानकर्ता के साथ योग्य नहीं होना चाहिए, बल्कि घोषणा को नामस्थान ब्लॉक के अंदर होना आवश्यक है जिसमें नया नाम घोषित किया जाना चाहिए।

वही नियम परिभाषाओं पर लागू होते हैं, क्योंकि वे एक घोषणा का संकेत देते हैं। मित्र घोषणा विशेष है, क्योंकि यह किसी अन्य परिभाषा के अंदर रहता है और वास्तव में कुछ भी घोषित नहीं करता है।

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