2010-09-09 5 views
7

के कारण टेम्पलेटेड फ़ंक्शन पर संदिग्ध कॉल मुझे इस समस्या से दो बार काट दिया गया है और इसलिए मेरे सहयोगी भी हैं।एडीएल

#include <deque> 
#include <boost/algorithm/string/find.hpp> 
#include <boost/operators.hpp> 

template< class Rng, class T >  
typename boost::range_iterator<Rng>::type find(Rng& rng, T const& t) { 
     return std::find(boost::begin(rng), boost::end(rng), t); 
} 

struct STest { 
     bool operator==(STest const& test) const { return true; } 
}; 

struct STest2 : boost::equality_comparable<STest2> { 
     bool operator==(STest2 const& test) const { return true; } 
}; 

void main() { 
     std::deque<STest> deq; 
     find(deq, STest()); // works 
     find(deq, STest2()); // C2668: 'find' : ambiguous call to overloaded function 
} 

संकलित करते समय ... दूसरे खोज को संकलित करते समय वीएस 9 कंपाइलर विफल रहता है। यह इस तथ्य के कारण है कि STest2 बूस्ट नेमस्पेस में परिभाषित एक प्रकार से विरासत प्राप्त करता है जो संकलक को एडीएल को आजमाने की कोशिश करता है जो boost::algorithm::find(RangeT& Input, const FinderT& Finder) पाता है।

एक स्पष्ट समाधान है find(…) पर :: "के साथ कॉल को उपसर्ग करना है, लेकिन यह आवश्यक क्यों है? वैश्विक नामस्थान में एक बिल्कुल वैध मिलान है, तो क्यों तर्क-निर्भर लुकअप का आह्वान करें? क्या कोई यहां तर्क को समझा सकता है?

+0

ध्यान दें कि मैच सही नहीं है। एक गैर-टेम्पलेट फ़ंक्शन 'ढूंढें (std :: डेक , स्टेस्ट);' एक बेहतर मैच होगा। – MSalters

+0

@MSalters: आप बिल्कुल सही हैं। वैश्विक नामस्थान में मैच सही नहीं है। मुझे लगता है कि मुझे एडीएल एक अपवाद होने की उम्मीद है, जो एक अधिक रिमोट नेमस्पेस में कड़ाई से बेहतर मिलान खोजने के लिए प्रयोग किया जाता है। जवाब यह एक गलतफहमी होने के लिए दिखाते हैं। – Sebastian

+0

मेरा सवाल यह है कि एडीएल 'बूस्ट :: एल्गोरिदम' के अंदर एक फ़ंक्शन क्यों ढूंढ रहा है जब तर्क वैश्विक नामस्थान में एक वर्ग है, जो 'बूस्ट :: विवरण' नामस्थान में किसी वर्ग से प्राप्त होता है ... और उत्तर एक है ' 'हेडर में एल्गोरिदम :: find' का उपयोग करके' फ़ंक्शन 'को' बूस्ट 'नेमस्पेस में लाता है। क्या यह एक दोष हो सकता है? क्या यह कम से कम वैकल्पिक नहीं होना चाहिए? –

उत्तर

7

ADL जब "सामान्य" अधिभार संकल्प में विफल रहता है उपयोग करने के लिए एक fallback तंत्र नहीं है, ADL द्वारा पाया कार्यों बस के रूप में करके पाया कार्यों के रूप में व्यावहारिक हैं सामान्य लुकअप

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

कार्य पिछले माना जाता है में

:

+0

धन्यवाद, आप सही हैं। मैंने एडीएल को नियम के बजाए अपवाद माना था, शायद सख्ती से बेहतर मिलान खोजने के लिए इस्तेमाल किया गया था। तो आपके तर्क के साथ, कंपाइलर को बेहतर मिलान खोजने के लिए अन्य नामस्थानों में जाना पड़ता है, लेकिन यदि वह देखता है और एक अलग-अलग मैच पाता है, तो त्रुटि के साथ असफल होने के लिए समझदारी की बात है। – Sebastian

3

मैं जोड़ देंगे स्पष्ट अपने आप का जवाब क्योंकि मैं सिर्फ इस समस्या पर कुछ शोध किया:

सी ++ 03 3.4.2

§2 समारोह कॉल में शामिल प्रत्येक तर्क प्रकार टी के लिए , वहाँ शून्य या अधिक संबद्ध नामस्थान का एक सेट है [...] नामस्थान और वर्गों के सेट निम्नलिखित तरीके से निर्धारित कर रहे हैं:

[...]

- अगर टी एक वर्ग प्रकार (है यूनियनों सहित), इसके associa टेड कक्षाएं हैं: कक्षा स्वयं; जिस वर्ग की यह सदस्य है, यदि कोई है; और इसके प्रत्यक्ष और अप्रत्यक्ष आधार वर्ग। इसके संबंधित नामस्थान नामस्थान हैं जिसमें इसके संबंधित वर्ग परिभाषित किए गए हैं।

§ 2 ए नाम की साधारण अयोग्य देखने एक वर्ग के सदस्य समारोह, जुड़े नामस्थान और कक्षाओं नहीं माना जाता है की घोषणा हो जाता है। अन्यथा के लुकअप द्वारा घोषित घोषणाओं का सेट फ़ंक्शन नाम सामान्य अयोग्य लुकअप और तर्क प्रकारों से जुड़े नामस्थानों और कक्षाओं में मिली घोषणाओं के सेट का उपयोग करके घोषित घोषणाओं के सेट का संघ है।

कम से कम यह मानक अनुरूप है, लेकिन मुझे अभी भी तर्क को समझ में नहीं आता है।

3

mystream पर विचार करें जो std::ostream से प्राप्त होता है। आप चाहते हैं कि आपका प्रकार सभी << ऑपरेटरों का समर्थन करेगा जो आमतौर पर std नेमस्पेस में std::ostream के लिए परिभाषित किए गए हैं। इसलिए बेस क्लास एडीएल के लिए कक्षाएं जुड़ी हैं।

मुझे लगता है कि यह प्रतिस्थापन सिद्धांत से भी पालन करता है - और कक्षा के नामस्थान में कार्यों को इसके इंटरफेस का हिस्सा माना जाता है (हर्ब सटर के "कक्षा में क्या है?" देखें)। तो आधार वर्ग पर काम करने वाला एक इंटरफेस व्युत्पन्न वर्ग पर काम करना चाहिए।

तुम भी ADL को अक्षम करके इस को हल करने के कर सकते हैं:

(find)(deq, STest2()); 
+0

ऑपरेटर तर्क कि चार्ल्स ने भी बनाया है निश्चित रूप से निश्चित है। यह वास्तव में आश्चर्य की बात नहीं है कि एडीएल के लिए बेस क्लास नेमस्पेस माना जाता है। मेरे असली दुनिया उदाहरण में यह टेम्पलेट तर्क नामस्थान है जो शामिल हो जाता है।बहुत आश्चर्यजनक, कम से कम जब तक मैं मानक पढ़ता हूं :-) – Sebastian

1

मुझे लगता है कि आप अपने आप को समस्या का वर्णन किया। यह परिभाषा द्वारा सबसे बाहरी क्षेत्र है। एक ही नाम (आवश्यक रूप से लागू नहीं) वाला कोई भी फ़ंक्शन जो निकटतम क्षेत्र में मिलता है (कॉल पॉइंट व्यू से) पहले उठाया जाएगा।

template <typename Rng, typename T> 
typename Rng::iterator find(Rng& rng, T const& t); 

namespace foo 
{ 
    bool find(std::vector<int> const& v, int); 

    void method() 
    { 
    std::deque<std::string> deque; 
    auto it = find(deque, "bar"); 
    } 
} 

यहाँ (जब तक vector या deque शामिल algorithm, जो अनुमति दी है), केवल विधि है कि नाम लुक-अप के दौरान उठाया जा जाएगा:

bool foo::find(std::vector<int> const&, int); 

algorithm तो किसी भी तरह शामिल किया गया है, वहां भी होगा:

template <typename FwdIt> 
FwdIt std::find(FwdIt begin, FwdIt end, 
       typename std::iterator_traits<FwdIt>::value_type const& value); 

और निश्चित रूप से, ओवरलोड रिज़ॉल्यूशन यह कहने में विफल रहेगा कि कोई मिलान नहीं है।

ध्यान दें कि नाम-लुकअप बेहद गूंगा है: न तो धैर्य और न ही तर्क प्रकार माना जाता है!

इसलिए, की मुक्त कार्यों कि तुम सी में उपयोग करना चाहिए ++ केवल दो प्रकार के होते हैं:

  • उन जो एक वर्ग, एक ही नाम स्थान में घोषित की इंटरफ़ेस का हिस्सा है, ADL
  • द्वारा उठाया
  • उन जो नहीं हैं, और आप इस प्रकार के

के मुद्दों से बचने के स्पष्ट रूप से योग्य होना चाहिए कि आप इन नियमों से बाहर हो जाते हैं, तो यह काम हो सकता है, या नहीं, क्या शामिल है पर निर्भर करता है, और कहा कि बहुत ही अजीब है।

+0

मेरा उदाहरण आपके से थोड़ा अलग है। मेरे उदाहरण में, एडीएल को नामस्थान में कार्यान्वयन मिल जाता है, कॉलर बिलकुल भी हिस्सा नहीं है। – Sebastian

+0

@ सेबेस्टियन: "कॉलर" संदिग्ध है। विचार करने के लिए दो चीजें हैं: कॉल का बिंदु, और तर्क। मेरा उदाहरण दोनों का प्रदर्शन किया, भले ही मैंने विरासत का उपयोग करके इसे और अधिक जटिल नहीं बनाया। –

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

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