2015-11-09 6 views
5

मैंने देखा कि std :: lower_bound() और std :: upper_bound() वाक्यविन्यास (अच्छी तरह से, प्रकार-रूपांतरण, वास्तव में) में असंगतता की तरह दिखता है और यह सोच रहा था कि कोई भी कृपया स्पष्ट कर सकता है? टिप्पणियों के अनुसार, लाइन 2 की स्पष्ट समानता के बावजूद लाइन 2 संकलित नहीं होगा; आप फार्म 3 लाइन पर दिखाया उपयोग करने की आवश्यकता (कम से कम जीसीसी पर 4.7.3/ubuntu 64-बिट - कि सभी के साथ मैं खेलने के लिए आपके पास यह है)ऊपरी_बाउंड और निचला_बाउंड असंगत मूल्य आवश्यकताओं

#include <set> 
#include <algorithm> 

using namespace std; 

class MyInt { 
    private: 
    int val; 
    public: 
    MyInt(int _val): val(_val) {} 
    bool operator<(const MyInt& other) const {return val < other.val;} 
}; 

int main() { 
    set<MyInt> s; 
    s.insert(1); // demonstrate implicit conversion works 
    s.insert(MyInt(2)); 
    s.insert(3); // one last one for the road 
    set<MyInt>::iterator itL = lower_bound(s.begin(), s.end(), 2); //LINE 1 
    // the line below will NOT compile 
    set<MyInt>::iterator itU = upper_bound(s.begin(), s.end(), 2); //LINE 2 
    // the line below WILL compile 
    set<MyInt>::iterator itU2 = upper_bound(s.begin(), s.end(), MyInt(2)); // LINE 3 
    return 0; 
} 
+0

यहां g ++ 4.8.4 के साथ समान व्यवहार। यह निश्चित रूप से एक जी ++ बग है। –

उत्तर

5

मैं इसे एक बग है नहीं लगता। आप (possible) implementation of std::upper_bound को देखें, तो तुलना की तरह

if (!(value < *it)) { ... } // upper_bound, implicit conversion `MyInt`->`int` doesn't work 

किया जाता है और क्योंकि operator<MyInt के एक सदस्य समारोह है (और int है, जो एक वर्ग प्रकार नहीं है की नहीं), कोड संकलन नहीं करता है, के बाद से MyInt से int पर कोई रूपांतरण नहीं है। दूसरी तरफ, std::lower_bound में, *it तुलना के एलएचएस पर दिखाई देता है, और value (प्रकार int) पर पर पूर्ण रूप से परिवर्तित किया जा सकता है।

if (*it < value) { ... } // lower_bound, implicit conversion `int`->`MyInt` works 

यही वजह है कि यह गैर-सदस्यों के रूप में तुलना ऑपरेटरों को लागू करने के लिए बेहतर है, तो आप इस विषमता नहीं है। स्कॉट मेयर्स 'Effective C++ पुस्तक: आइटम 24: गैर-सदस्य फ़ंक्शंस घोषित करें जब सभी प्रकार के पैरामीटर पर रूपांतरण लागू होना चाहिए।

त्वरित और गंदे ठीक: int लिए अंतर्निहित रूपांतरण MyInt के लिए एक MyInt::operator int(){return val;} परिभाषित करते हैं। (संपादित करें: वास्तव में काम नहीं करता है, अस्पष्टता)। अंतर्निहित रूपांतरण

set<MyInt>::iterator itU = upper_bound(s.begin(), s.end(), MyInt(2)); 

इसके बजाय अंतर्निहित रूपांतरण की आवश्यकता को हटा रहा है।

+0

अच्छा खुदाई, धन्यवाद! दिलचस्प है कि एसटीएल कार्यान्वयन (तर्कसंगत) अपने इंटरफेस को उलझन में डालता है। फिर भी एक और कारण निहित प्रकार रूपांतरणों को नाराज करने के लिए – aho

+0

@ हां हां, एक अच्छा अच्छा कारण, महान सवाल btw। 'Std :: upper_bound' शायद" निश्चित "हो सकता है यदि हम' value' से '* it' तक अतिरिक्त रूपांतरण करते हैं और इसे अस्थायी रूप में संग्रहीत करते हैं, तो तुलना में उत्तरार्द्ध का उपयोग करें। इस मामले में, व्यवहार 'std :: lower_bound' के समान ही होगा, और भुगतान करने की कोई कीमत नहीं है (यदि आप कोड को संकलित करना चाहते हैं तो आप इसे वैसे भी भुगतान करते हैं)। – vsoftco

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