क्या Bjarne ADL के इस उदाहरण के बारे में गलत है, या क्या मेरे पास कंपाइलर बग है?


81

मैं C ++ प्रोग्रामिंग लैंग्वेज, 4th एडिशन ( Bjarne Stroustrup द्वारा ) के बारे में पढ़ रहा हूँ। यहाँ बोली (26.3.6, अतिशयोक्तिपूर्ण ADL) है:

तर्क-निर्भरता देखने (अक्सर ADL के रूप में संदर्भित) वर्बोसिटी (14.2.4) से बचने के लिए बहुत उपयोगी है। उदाहरण के लिए:

#include <iostream>

int main()
{
    std::cout << "Hello, world" << endl; // OK because of ADL
}

तर्क-निर्भर लुकअप के बिना, endlमैनिपुलेटर नहीं मिलेगा। यह, संकलक नोटिस के रूप में करने के लिए कि पहले तर्क <<एक है ostreamमें परिभाषित किया std। इसलिए, यह खोजता endlहै stdऔर इसे (में <iostream>) पाता है ।

और यहाँ संकलक द्वारा उत्पादित परिणाम (C ++ 11 मोड):

prog.cpp: In function ‘int main()’:
prog.cpp:4:36: error: ‘endl’ was not declared in this scope
 std::cout << "Hello, world" << endl;
                                ^

या तो यह कंपाइलर या किताब में एक बग है। मानक क्या कहता है?

अपडेट करें:

मुझे थोड़ा स्पष्ट करने की आवश्यकता है। मुझे पता है कि सही उत्तर का उपयोग करना है std::endl। प्रश्न पुस्तक में पाठ के बारे में था। जैसा कि लछलन ईस्टन ने पहले ही कहा था, यह केवल एक टाइपो नहीं है। पूरा पैराग्राफ (शायद) गलत है। मैं इस तरह की त्रुटि को स्वीकार कर सकता हूं यदि पुस्तक एक अन्य (कम ज्ञात) लेखक द्वारा है, लेकिन मैं संदेह में था (और अभी भी हूं) क्योंकि यह बज़्ने द्वारा लिखा गया था।


12
std::endlकोई बग नहीं
अरोनमैन 17

3
मेरे अनुभव में, किताबें बग और टाइपोस के लिए कुख्यात हैं। एक अच्छी किताब में उम्मीद है कि केवल मामूली / स्पष्ट।
नील कर्क

31
@ ओरणमन ओपी स्पष्ट रूप से इससे अवगत है। उद्धरण से, ऐसा प्रतीत होता है कि बज़्ने (C ++ का निर्माता) दावा कर रहा है कि std::ADL के कारण इस मामले में आवश्यक नहीं है। लेकिन यह संकलन नहीं है, इसलिए प्रश्न।
ब्लूराजा - डैनी पफ्लुगुएफ्ट

6
हां, बात यह है कि पुस्तक स्पष्ट रूप से गलत बात कहती है। यह टाइपो नहीं है, वास्तव में सच नहीं है, यह वर्णन करने के लिए एक पूरा पैराग्राफ लिखा गया था। यह किताब में एक बग है।
डेनियलको

7
@maverik यह है किताब में एक त्रुटि। मैंने कुछ मिनट पहले उन्हें इस मुद्दे की सूचना दी, मैं आपको उनके उत्तर के बारे में बताऊंगा।
अली

जवाबों:


83

यह संकलक में बग नहीं है। ADL का उपयोग कार्यों को देखने के लिए किया जाता है न कि तर्कों के लिएoperator<<एडीएल के माध्यम से यहां पाया जाने वाला कार्य मापदंडों std::coutऔर (क्या होना चाहिए) को देखकर है std::endl


2
वास्तव में, पूर्वव्यापी में यह इस तथ्य का फायदा उठाकर कोड को वैध बनाने का एक तरीका प्रेरित करता है जो एक तथ्य के std::endlरूप में है (और भ्रामक रूप से) एक फ़ंक्शन:endl(std::cout << "Hello, world"); // OK because of ADL
अल्फेक

49

यह कहने वालों के लिए यह टाइपो नहीं है। या तो बज़्ने ने गलती की या कंपाइलर ने इसे गलत बताया। ओपी द्वारा पोस्ट एक के बाद पैराग्राफ पढ़ता है

तर्क-निर्भर लुकअप के बिना, एंडल मैनिपुलेटर नहीं मिलेगा। जैसा कि यह है, संकलक ने नोटिस किया कि << का पहला तर्क एसटीडी में परिभाषित एक ओस्ट्रीम है। इसलिए, यह एसटीडी में एंडल के लिए दिखता है और इसे (में <iostream>) पाता है ।


18
आपको लगता है कि श्रीमान यहां एकमात्र ऐसे व्यक्ति हैं जो वास्तव में इसे पुस्तक पर पढ़ते हैं। यह या तो भाषा के नियमों में एक महत्वपूर्ण बदलाव है, सभी मौजूदा C ++ कंपाइलरों को गैर-मानक (C ++ 11 के लिए) बना रहा है, या श्री स्ट्रॉस्ट्रुप (और न केवल एक टाइपो) से एक चमकदार त्रुटि। बल्कि मैंने एक संशोधित संस्करण प्राप्त करने के लिए दो अतिरिक्त महीनों की प्रतीक्षा की है। उसने अपनी दाढ़ी को वापस बेहतर कर लिया।
डेनियलको

वैसे, मार्कअप ने बोली में आखिरी बिट खाया, आप शायद बैकटिक्स का उपयोग करना चाहते हैं, "(इन <iostream>)।"
डेनियलको

20

यह पुस्तक में एक टाइपो है क्योंकि अन्य लोग पहले ही बता चुके हैं। हालाँकि, इस पुस्तक का क्या मतलब है, यह हमें लिखना होगा

std::operator<<(std::cout, "Hello, world").operator<<(std::endl);

ADL के बिना। यही बज्ने का मतलब क्रिया से है।


मुझे सही साबित होना है। जैसा कि लाचलैन ईस्टन बताते हैं, यह टाइपो नहीं है, बल्कि पुस्तक में एक गलती है। मेरे पास इस पुस्तक तक पहुंच नहीं है, इसलिए मैं उस अनुच्छेद को नहीं पढ़ सका और इसे स्वयं महसूस कर सका। मैंने बज्ने को यह गलती बताई है ताकि वह इसे सुधार सके।


मजेदार। ऐसा ही उदाहरण विकिपीडिया और पर है

ध्यान दें कि std::endlयह एक फ़ंक्शन है लेकिन इसे पूर्ण योग्यता की आवश्यकता है, क्योंकि इसका उपयोग एक तर्क के रूप में किया जाता है operator<<( std::endlयह फ़ंक्शन पॉइंटर है, फ़ंक्शन कॉल नहीं है)।

इसमें कोई शक नहीं, यह पुस्तक में एक गलती है। फिर भी उदाहरण से std::operator<<(std::cout, "Hello, world").operator<<(std::endl);पता चलता है कि ADL कैसे क्रिया को कम करने में मदद करता है।


मेरी गलती को इंगित करने के लिए gx_ का धन्यवाद ।


यह एक टाइपो से अधिक था, उसने कुछ के बारे में सोचा (कैसे std::operator<<होता है) का पता लगाया और गलत जानकारी के साथ एक पूरा पैराग्राफ लिखा। यह वास्तव में आपको विश्वास दिलाता है कि एडीएल के नियम बदल गए हैं और संकलनकर्ता अब टूट गए हैं।
डेनियलको

वास्तव में पुस्तक में काफी कुछ टाइपो लगता है जैसे 17.2.5
एंडर्सके

@DanielKO मैं सही खड़ा हूँ; मैंने अपना जवाब तय कर दिया है, धन्यवाद। मेरे पास इस पुस्तक तक पहुंच नहीं है, इसलिए मैंने सोचा कि यह एक टाइपो था। किसी भी मामले में, ADL शब्दशः को कम करने में मदद करता है, और मैंने जो कोड दिया है, वह उसी का एक उदाहरण है। किसी भी मामले में, मुझे बताने के लिए धन्यवाद।
अली

वास्तव में हमें जो लिखना होगा वह वास्तव में है std::operator<<(std::cout, "Hello, world").operator<<(std::endl);( गैर-सदस्यoperator<< और सदस्य देखेंoperator<< )
gx_

10

संकेत "तर्क-निर्भर लुकअप" नाम में है।

यह अयोग्य फ़ंक्शन नामों के लिए खोज है, जो तर्कों के आधार पर काम करता है

यह तर्क के लिए देखने के साथ कुछ नहीं मिला है।

बज्ने चूक।


8

मेरे पास पुस्तक नहीं है, लेकिन यह पुस्तक में एक त्रुटि प्रतीत होती है, तथ्य यह है कि यह नामस्थान योग्यताधारी गायब है इसका ADL से कोई लेना-देना नहीं है। यह होना चाहिए std::endl


1
मैं सहमत हूँ। लेकिन यह अजीब बयान है (मेरा मतलब किताब में एक है)। मुझे उम्मीद है कि बज्ने को इसके बारे में पता होना चाहिए।
मवरिक

@maverik शायद वह पहले से ही करता है, मुझे आश्चर्य नहीं होगा कि किसी ने पहले ही यह सूचना दी थी। यदि नहीं, तो आप :)
बोर्गेल्डर

@maverik यह वास्तव में सिर्फ एक टाइपो है, मुझे लगता है कि किसी और ने पहले ही इस पर ध्यान दिया होगा
aaronman

2
हां, वास्तव में, मैंने सभी बयान को गलत समझा (साथ std::cout) वह खोज करने के बारे में बात कर रहा था operator<<, नहीं endl
Maverik

4

हां, यह एक त्रुटि है - उदाहरण बीमार है और इसका संकलन नहीं किया जाना चाहिए। ADL फ़ंक्शन कॉल अभिव्यक्तियों को लागू करने वाले अयोग्य सूची नामों पर लागू होता है। endlदेखने के लिए एक आईडी-अभिव्यक्ति का प्रयास है std::endlendlएक फ़ंक्शन कॉल अभिव्यक्ति पेश नहीं करता है इसलिए तर्क-निर्भर लुकअप का उपयोग इसके लिए नहीं किया जाता है, केवल अयोग्य लुकअप का उपयोग किया जाता है, इसलिए यह std::endlइच्छित के रूप में नहीं मिलेगा ।

एक सरल और सही उदाहरण होगा:

#include <vector>

int main()
{
    std::vector<int> x, y;
    swap(x,y); // calls std::swap due to ADL
}

सारांश में, f(x,y,z)एक अयोग्य आईडी (जैसे ) के साथ एक फ़ंक्शन कॉल (जैसे ) से fपहले देखा जाता है, पहले फ़ंक्शन (जैसे x,y,z) के मापदंडों का विश्लेषण उनके प्रकार को निर्धारित करने के लिए किया जाता है। प्रकारों के आधार पर संबद्ध नामस्थानों की एक सूची बनाई जाती है (उदाहरण के लिए प्रकार की परिभाषा का संलग्न नामस्थान एक संबद्ध नामस्थान है)। इन नामस्थानों को तब फ़ंक्शन के लिए अतिरिक्त रूप से खोजा जाता है।

बज्ने के उदाहरण का उद्देश्य std::operator<<फ़ंक्शन के एडीएल को दिखाना है , और नहीं std::endl। इसके लिए एक अतिरिक्त समझ की आवश्यकता होती है कि अतिभारित ऑपरेटर वास्तव में फ़ंक्शन कॉल अभिव्यक्तियाँ हैं, इसलिए x << yइसका मतलब है operator<<(x,y), और operator<<एक अयोग्य नाम है, और इसलिए ADL इस पर लागू होता है। LHS का प्रकार std::ostreamइतना stdसंबद्ध नाम स्थान है, और इसलिए std::operator<<(ostream&, ...)पाया जाता है।

सुधरी हुई कमेंट्री पढ़नी चाहिए:

तर्क-निर्भर लुकअप के बिना, नामस्थान <<में ओवरलोड ऑपरेटर stdनहीं मिलेगा। जैसा कि यह है, संकलक ने नोटिस किया कि << का पहला तर्क एसटीडी में परिभाषित एक ओस्ट्रीम है। इसलिए, यह <<std में ऑपरेटर की तलाश करता है और इसे (में <iostream>) पाता है ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.