भाषा विनिर्देश वैश्विक नामस्थान में मानक कार्यों को घोषित (और परिभाषित) करके कार्यान्वयन के लिए कार्यान्वयन की अनुमति देता है और फिर उपयोग-घोषणाओं के माध्यम से उन्हें नामस्थान में लाया जाता है। यह अनिर्दिष्ट है कि क्या इस दृष्टिकोण का उपयोग किया जाता है<cmath>std
20.5.1.2 हेडर्स
4 [...] सी ++ मानक पुस्तकालय में, हालांकि, घोषणाएं (सी में मैक्रोज़ के रूप में परिभाषित किए गए नामों को छोड़कर) नाम स्थान के नाम स्थान (6.3.6) के भीतर हैं std। यह अनिर्दिष्ट है कि क्या ये नाम (क्लॉज़ 21 में 33 और एनेक्स डी के माध्यम से जोड़े गए किसी भी अधिभार सहित) को पहले वैश्विक नाम स्थान के दायरे में घोषित किया गया है और फिर stdस्पष्ट उपयोग-घोषणाओं (10.3.3) द्वारा नामस्थान में अंतःक्षिप्त किया गया है।
जाहिरा तौर पर, आप इस दृष्टिकोण (जैसे जीसीसी) का पालन करने का फैसला करने वाले कार्यान्वयन में से एक के साथ काम कर रहे हैं। यानी आपका कार्यान्वयन प्रदान करता है ::abs, जबकि std::absबस "संदर्भित" करता है ::abs।
इस मामले में एक सवाल यह है कि मानक के अलावा ::absआप अपनी खुद की घोषणा करने में सक्षम ::absक्यों थे, अर्थात कोई एकाधिक परिभाषा त्रुटि क्यों नहीं है। यह कुछ कार्यान्वयनों (जैसे जीसीसी) द्वारा प्रदान की गई एक अन्य विशेषता के कारण हो सकता है: वे मानक कार्यों को तथाकथित कमजोर प्रतीकों के रूप में घोषित करते हैं , इस प्रकार आप उन्हें अपनी परिभाषाओं के साथ "प्रतिस्थापित" करने की अनुमति देते हैं।
ये दो कारक मिलकर आपके द्वारा बनाए गए प्रभाव का निर्माण करते हैं: कमजोर-प्रतीक प्रतिस्थापन के ::absपरिणामस्वरूप भी प्रतिस्थापन होता है std::abs। भाषा मानक के साथ यह कितनी अच्छी तरह से सहमत है एक अलग कहानी है ... किसी भी मामले में, इस व्यवहार पर भरोसा न करें - यह भाषा की गारंटी नहीं है।
जीसीसी में इस व्यवहार को निम्नलिखित न्यूनतर उदाहरण द्वारा पुन: प्रस्तुत किया जा सकता है। एक स्रोत फ़ाइल
#include <iostream>
void foo() __attribute__((weak));
void foo() { std::cout << "Hello!" << std::endl; }
एक अन्य स्रोत फ़ाइल
#include <iostream>
void foo();
namespace N { using ::foo; }
void foo() { std::cout << "Goodbye!" << std::endl; }
int main()
{
foo();
N::foo();
}
इस मामले में आप यह भी देखेंगे कि दूसरी स्रोत फ़ाइल में ::foo( "Goodbye!") की नई परिभाषा के व्यवहार को भी प्रभावित करता है N::foo। दोनों कॉल आउटपुट करेंगे "Goodbye!"। और यदि आप ::fooदूसरी स्रोत फ़ाइल से परिभाषा को हटाते हैं , तो दोनों कॉल "मूल" ::fooऔर आउटपुट की परिभाषा को भेज देंगे "Hello!"।
उपरोक्त 20.5.1.2/4 द्वारा दी गई अनुमति के कार्यान्वयन को सरल बनाने के लिए है <cmath>। कार्यान्वयन को केवल सी-शैली में शामिल करने की अनुमति है <math.h>, फिर कार्यों को फिर से stdजोड़ने और कुछ सी ++ - विशिष्ट परिवर्धन और ट्वीक्स जोड़ें। यदि उपरोक्त स्पष्टीकरण मुद्दे के आंतरिक यांत्रिकी का ठीक से वर्णन करता है, तो इसका एक प्रमुख हिस्सा कार्यों के सी-शैली संस्करणों के लिए कमजोर प्रतीकों की पुनरावृत्ति पर निर्भर करता है।
ध्यान दें कि यदि हम उपरोक्त कार्यक्रम में केवल विश्व स्तर पर प्रतिस्थापित intकरते हैं double, तो कोड (GCC के तहत) "अपेक्षित रूप से व्यवहार करेगा" - यह आउटपुट होगा -5 5। ऐसा इसलिए होता है क्योंकि C मानक लाइब्रेरी में abs(double)फ़ंक्शन नहीं होता है। अपनी खुद की घोषणा करके abs(double), हम कुछ भी प्रतिस्थापित नहीं करते हैं।
लेकिन अगर से स्विच करने के बाद intसाथ doubleहम भी से स्विच absकरने के लिए fabs, मूल अजीब व्यवहार अपनी पूरी महिमा (उत्पादन में फिर से दिखाई देगा -5 -5)।
यह उपरोक्त स्पष्टीकरण के अनुरूप है।
absगलत है।