2016-08-16 6 views
6

std :: cd+ प्रकार का libcxx (C++ मानक लाइब्रेरी का llvm संस्करण) समान तत्व के साथ तुलना अनुमानित करता है यानी तुलनात्मक विक्टर के तर्क दोनों को संदर्भित करते हैं अनुक्रमित करने के क्रम में स्थिति। बिंदु को चित्रित करने के लिए एक संक्षिप्त उदाहरण।तुलनात्मक फ़ंक्शन

$ cat a.cc 
#include <algorithm> 
#include <vector> 
#include <cassert> 

int main(int argc, char** argv) { 
    int size = 100; 
    std::vector<int> v(size); 

    // Elements in v are unique. 
    for (int i = 0; i < size; ++i) 
    v[i] = i; 

    std::sort(v.begin(), v.end(), 
      [&](int x, int y) { assert(x != y); return x < y; }); 

    return 0; 
} 

$ clang++ -std=c++11 -stdlib=libc++ a.cc -o a.out 
$ ./a.out 
a.out: a.cc:14: auto main(int, char **)::(anonymous class)::operator()(int, int) const: Assertion `x != y' failed. 
./go.sh: line 5: 19447 Aborted     (core dumped) ./a.out 

libstdC++ के साथ ठीक काम करता है।

$ clang++ -std=c++11 -stdlib=libstdc++ a.cc -o a.out 
$ ./a.out 

क्या यह समान तत्व के साथ तुलना फ़ंक्शन को कॉल करना ठीक है। यह अनावश्यक नहीं है।

+0

"क्या यह ठीक है" से आपका क्या मतलब है? क्या आप पूछ रहे हैं कि मानक द्वारा इसकी अनुमति है या नहीं? –

+1

मुझे नहीं लगता कि मानक की ऐसी कोई आवश्यकता है, मैं ज्यादातर एल्गोरिदमिक दृष्टिकोण से रूचि रखता हूं कि क्यों कोई भी समान तत्व के साथ तुलना फ़ंक्शन को कॉल करेगा। क्या यह किसी भी मौके से तेजी से छंटनी करता है, या यह सिर्फ एक बग है। –

+0

एफवाईआई, https://llvm.org/bugs/show_bug.cgi?id=20837 –

उत्तर

2

मैं इस प्रश्न पर कुछ अधिकारियों के साथ बात कर सकता हूं क्योंकि मैं यह कोड लिखता हूं।

https://github.com/llvm-mirror/libcxx/blob/master/include/algorithm#L3994-L3995

के रूप में लिंक (गलत लाइन के लिए बिंदु) जाने के लिए बासी के रूप में समय पर चला जाता है की संभावना है, मैं भी बोली होगी:

यहाँ तुलना जो अपने उदाहरण में जोर देते हुए किया जाता है यहाँ कोड:

  // __m still guards upward moving __i 
      while (__comp(*__i, *__m)) 
       ++__i; 

यह इटरेटर __i अनुक्रम के अंत बंद चल रहा है के रूप में यह वृद्धि की जाती है के लिए कोई चेक न होने के कारण एक "असुरक्षित" लूप के रूप में जाना जाता है। इस कारण का कारण यह है क्योंकि इस एल्गोरिदम का एक आविष्कार यह है कि इस बिंदु पर यह ज्ञात है कि __i <= __m (जो इस उद्धरण के ऊपर एक टिप्पणी में 3 पंक्तियों में भी है)।

आप इस बोली से ऊपर कोड को देखें, तो आप इन टिप्पणियों देखेंगे:

// The search going up is known to be guarded but the search coming down isn't. 
    // Prime the downward search with a guard. 

तो इससे पहले कि हम इस बात पर आते हैं, अनुक्रम नीचे एक सुरक्षित खोज किया जाता है। यही कारण है कि, इस परीक्षण है:

if (__i == --__j) 

इस परीक्षण के बाद कम गार्ड पाता है, एल्गोरिथ्म तो, निगरानी रहित छोरों जो यात्रा में केवल एक परीक्षण के लिए कूदता है जबकि अन्यथा यात्रा प्रति दो टेस्ट (पर एक परीक्षण किया जाएगा इटरेटर और इटरेटर के मानदंडित मूल्य पर एक परीक्षण)।

"अनगिनत लूप" का उपयोग एक तत्व का तुलना स्वयं के साथ किया जा रहा है। विकास के दौरान मैंने मापा कि लूप में एक अतिरिक्त तुलना की लागत लूप में प्रति पुनरावृत्ति के दो तुलनाओं की तुलना में एक बेहतर सौदा था।

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

यह उत्तर rici's answer के साथ पूरी तरह से संगत है जो भी सही है (और मैंने इसे ऊपर उठाया है)।मैंने अपनी आवाज़ को जोड़ा क्योंकि मैं "संभावित रूप से" छोड़ सकता हूं और एल्गोरिदम में कोड की विशिष्ट पंक्तियों को इंगित करता हूं।

+0

उत्तर के लिए धन्यवाद, मुझे अभी भी आश्चर्य है कि यह एक अच्छा विचार है क्योंकि, बाद में, IIUC, यह भी उसी तत्व पर स्वैप कहता है। इसके अलावा, इस प्रकार एल्गोरिदम ओ (एन^2) https://llvm.org/bugs/show_bug.cgi?id=20837 है, मानक को O (nlogn) की आवश्यकता है। यह मेरा प्रश्न नहीं है लेकिन मैंने इसका उल्लेख किया क्योंकि आप इस एल्गोरिदम के मूल लेखक हैं। –

+0

ओ (एन^2) मुद्दा अलग-अलग है। जो कुछ करने की जरूरत है वह ट्रैक qsort गहराई है और एक सीमा तक पहुंचने पर हीप प्रकार पर स्विच करें। –

2

संभावित रूप से, मानक-लाइब्रेरी लेखकों की राय में, यह एक ऐसा परीक्षण करना तेज़ है जो लगातार बराबर सूचकांक के साथ-साथ तत्वों की तुलना करने के लिए झूठी वापसी की गारंटी देता है। यह इस बारे में आ सकता है क्योंकि पिवट तत्व को लूप सेंटीनेल के रूप में उपयोग किया जाता है।

इस तरह से तुलनात्मक फ़ंक्शन को इस तरह से कॉल करने की अनुमति है, और आपके कोड में assert की अनुमति नहीं है।

+0

जोर देने की अनुमति क्यों नहीं दी जाएगी? –

+0

लेकिन यदि तुलना फ़ंक्शन कम_equal है, तो यह सही होगा जब दोनों तर्क समान होते हैं, उस स्थिति में फ़ंक्शन एक ही तत्व 'स्वैप' करेगा, या कम से कम स्वैप दिनचर्या को कॉल करेगा। –

+0

@ एके .: less_equal मान्य तुलनित्र नहीं है। – rici

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