2017-10-08 15 views
6

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

#include <algorithm> 
#include <iostream> 
#include <set> 

struct partial_compare : std::less<> 
{ 
    //"full" key_type comparison done by std::less 
    using less<>::operator(); 

    //"sequence-partitioning" comparison: only check pair's first member 
    bool operator()(std::pair<int, int> const &lhs, int rhs) const 
    { 
     return lhs.first < rhs; 
    } 

    bool operator()(int lhs, std::pair<int, int> const &rhs) const 
    { 
     return lhs < rhs.first; 
    } 
}; 

int main() 
{ 
    //Using std::set's lookup 
    { 
     std::cout << "std::set's equal_range:\n"; 
     std::set <std::pair<int, int>, partial_compare> s{{1,0},{1,1},{1,2},{1,3},{2,0}}; 

     auto r = s.equal_range (1); 

     for (auto it = r.first; it != r.second; ++it) 
     { 
      std::cout << it->first << ", " << it->second << '\n'; 
     } 

     std::cout << "std::set's lower_bound + iteration on equivalent keys:\n"; 
     auto lb = s.lower_bound(1); 

     while (lb != std::end(s) && !s.key_comp()(lb->first, 1) && !s.key_comp()(1, lb->first)) 
     { 
      std::cout << lb->first << ", " << lb->second << '\n'; 
      ++lb; 
     } 
    } 

    //Using algorithms on std::set 
    { 
     std::cout << "std::equal_range\n"; 
     std::set <std::pair<int, int>> s{{1,0},{1,1},{1,2},{1,3},{2,0}}; 

     auto r = std::equal_range (std::begin(s), std::end(s), 1, partial_compare{}); 
     for (auto it = r.first; it != r.second; ++it) 
     { 
      std::cout << it->first << ", " << it->second << '\n'; 
     } 
    } 
    return 0; 
} 

जब बजना -5/libC++ के साथ संकलित निम्नलिखित उत्पादन का उत्पादन:

std::set's equal_range: 
1, 1 
std::set's lower_bound + iteration on equivalent keys: 
1, 0 
1, 1 
1, 2 
1, 3 
std::equal_range 
1, 0 
1, 1 
1, 2 
1, 3 

और निम्नलिखित जब साथ संकलित जीसीसी-7.1.0:

std::set's equal_range: 
1, 0 
1, 1 
1, 2 
1, 3 
std::set's lower_bound + iteration on equivalent keys: 
1, 0 
1, 1 
1, 2 
1, 3 
std::equal_range 
1, 0 
1, 1 
1, 2 
1, 3 

प्रारंभिक N3465 प्रस्ताव पढ़कर, मुझे लगता है कि मैं जो कर रहा हूं वह ठीक और अवधारणात्मक रूप से समान होना चाहिए जो प्रो में है पॉशल का प्रारंभिक उदाहरण: लुकअप के दौरान "आंशिक मिलान", "अनुक्रम विभाजन की धारणा" पर निर्भर करता है।
अब, यदि मैं सही ढंग से समझ रहा हूं, तो मानक में वास्तव में क्या हुआ N3657 है, लेकिन यह अवधारणा को बदलने के लिए प्रतीत नहीं होता है क्योंकि यह "बस" प्रदान करता है ताकि विषम लुकअप सदस्य टेम्पलेट केवल उपलब्ध कराए जाने पर उपलब्ध हो जाएं तुलनित्र "is_transparent" है।
तो, मैं वास्तव में समझ नहीं पा रहा हूं कि stang :: set's equal_range क्लैंग/libC++ में सदस्य टेम्पलेट का उपयोग क्यों जीसीसी या समकक्ष "lower_bound + स्कैन" के समान परिणाम उत्पन्न नहीं करता है। क्या मुझे कुछ याद आ रहा है और इस तरह से विषम लुकअप का उपयोग वास्तव में मानक का उल्लंघन कर रहा है (और फिर क्लैंग सही है और equal_range और lower_bound + स्कैन यूबी के कारण हो सकता है), या क्लैंग/libC++ गलत है?

संपादित करें: अब स्वीकृत उत्तर पढ़ने के बाद, मैं libC++ के लिए प्रासंगिक bug report ढूंढने में सक्षम था।
equal_range के व्यवहार में अंतर के बारे में एक विशिष्ट प्रश्न भी है जो libC++ और libstdC++ here के बीच टेम्पलेट सदस्यों के बीच है जो मुझे अपनी खोज करते समय नहीं मिला।
सुनिश्चित नहीं है कि यह हटाया जाना चाहिए या बंद किया जाना चाहिए, क्योंकि मैंने जो लिंक किया है, उसके पास एक स्वीकृत उत्तर नहीं है।

+0

'upper_bound' को इटरेट करना बहुत साफ होगा। – o11c

+0

@ o11c सच है, लेकिन चूंकि क्या झगड़ा कर रहा है, इस बारे में संदेह में, मैंने पूरी तरह से "मैन्युअल" दृष्टिकोण का उपयोग करना पसंद किया ताकि समान समस्या से काटने की संभावना को कम किया जा सके जो बराबर_रेंज को प्रभावित कर सकता है। – abigagli

उत्तर

6

यह libC++ में एक बग है: इसकी equal_range implementation (r315179 पर) तुरंत विषम तुलना के साथ "बराबर" तत्व खोजने पर दोनों इटरेटर्स को लौटाता है।

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

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