पारदर्शी तुलनित्र क्या हैं?


106

C ++ 14 में, साहचर्य कंटेनरों को C ++ 11 से बदल दिया गया लगता है - [सहयोगी .reqmts] / 13 कहते हैं:

सदस्य समारोह टेम्पलेट्स find, count, lower_bound, upper_bound, और equal_rangeअधिभार संकल्प में जब तक प्रकार भाग नहीं करेगा Compare::is_transparentमौजूद है।

एक तुलनित्र को "पारदर्शी" बनाने का उद्देश्य क्या है?

C ++ 14 भी इस तरह से लाइब्रेरी टेम्पलेट प्रदान करता है:

template <class T = void> struct less {
    constexpr bool operator()(const T& x, const T& y) const;
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef bool result_type;
};

template <> struct less<void> {
    template <class T, class U> auto operator()(T&& t, U&& u) const
    -> decltype(std::forward<T>(t) < std::forward<U>(u));
    typedef *unspecified* is_transparent;
};

उदाहरण के लिए, std::set<T, std::less<T>>होगा नहीं एक पारदर्शी तुलनित्र है, लेकिन std::set<T, std::less<>> होता एक है।

यह किस समस्या को हल करता है, और क्या यह बदलता है कि मानक कंटेनर कैसे काम करते हैं? उदाहरण के लिए, की टेम्प्लेट पैरामीटर std::setअभी भी कर रहे हैं Key, Compare = std::less<Key>, ..., तो डिफ़ॉल्ट सेट अपने खो find, countआदि सदस्यों?


उदाहरण के लिए, इस संक्षिप्त विवरण को देखें । और मैं अब बेवकूफ महसूस कर रहा हूं, क्योंकि मैं "सदस्य फ़ंक्शन टेम्पलेट " शब्द नहीं देख रहा हूं ...
21:30 पर केरेक एसबी

5
संभवतः संबंधित: stackoverflow.com/questions/18939882/…

जवाबों:


60

इससे क्या समस्या हल होती है,

देखें डिटमार के जवाब और remyabel का जवाब

और क्या यह बदलता है कि मानक कंटेनर कैसे काम करते हैं?

नहीं, डिफ़ॉल्ट रूप से नहीं।

नए सदस्य फंक्शन टेम्प्लेट ओवरलोड्स findआदि आपको एक प्रकार का उपयोग करने की अनुमति देते हैं जो कुंजी के प्रकार का उपयोग करने के बजाय कंटेनर की कुंजी के साथ तुलनीय है। राशनेल और एक विस्तृत, ध्यान से लिखित प्रस्ताव इस सुविधा को जोड़ने के लिए Joaquín M34 López Muñoz द्वारा N3465 देखें ।

ब्रिस्टल बैठक में एलडब्ल्यूजी ने सहमति व्यक्त की कि विषम दिखने वाला फीचर उपयोगी और वांछनीय था, लेकिन हम यह सुनिश्चित नहीं कर सकते थे कि जोएक्विंस का प्रस्ताव सभी मामलों में सुरक्षित होगा। N3465 प्रस्ताव ने कुछ कार्यक्रमों के लिए गंभीर समस्याएँ पैदा की हैं ( मौजूदा कोड अनुभाग पर प्रभाव देखें )। जोकिन ने अलग-अलग ट्रेड-ऑफ के साथ कुछ वैकल्पिक कार्यान्वयन के साथ एक अद्यतन मसौदा प्रस्ताव तैयार किया, जो एलडब्ल्यूजी को पेशेवरों और विपक्षों को समझने में मदद करने के लिए बहुत उपयोगी था, लेकिन उन्होंने सभी कार्यक्रमों को किसी तरह से तोड़ने का जोखिम उठाया, ताकि सुविधा को जोड़ने के लिए कोई आम सहमति न हो। हमने तय किया कि यद्यपि यह सुविधा को बिना शर्त जोड़ना सुरक्षित नहीं होगा, यह सुरक्षित होगा यदि इसे डिफ़ॉल्ट रूप से अक्षम किया गया था और केवल "ऑप्ट इन" किया गया था।

के मुख्य अंतर यह है N3657 प्रस्ताव (जो के आधार पर अपने आप को और एसटीएल द्वारा एक आखिरी मिनट संशोधन था N3465 और जोकिन से एक बाद की अप्रकाशित मसौदा) जोड़ने के लिए था is_transparentप्रोटोकॉल है कि नई कार्यक्षमता में चुनने के लिए इस्तेमाल किया जा सकता के रूप में लिखें।

यदि आप एक "पारदर्शी फ़ंक्टर" (यानी एक is_transparentप्रकार को परिभाषित करता है ) का उपयोग नहीं करते हैं, तो कंटेनर उसी तरह का व्यवहार करते हैं जैसा उन्होंने हमेशा किया है, और यह अभी भी डिफ़ॉल्ट है।

Iff आप का उपयोग करने के लिए चुनते हैं std::less<>(जो C ++ 14 के लिए नया है) या किसी अन्य "पारदर्शी फ़ंक्टर" प्रकार के बाद आपको नई कार्यक्षमता मिलती है।

std::less<>अन्य उपनामों के साथ प्रयोग करना आसान है:

template<typename T, typename Cmp = std::less<>, typename Alloc = std::allocator<T>>
  using set = std::set<T, Cmp, Alloc>;

यह नाम is_transparentSTL के N3421 से आया है जिसने "डायमंड ऑपरेटर्स" को C ++ 14 में जोड़ा है। एक "पारदर्शी फ़ंक्टर" वह है जो किसी भी प्रकार के तर्क को स्वीकार करता है (जो कि समान होना जरूरी नहीं है) और बस उन तर्कों को किसी अन्य ऑपरेटर को अग्रेषित करता है। इस तरह के एक फ़नकार को वही होता है जो आप साहचर्य कंटेनरों में विषम खोज के लिए चाहते हैं, इसलिए प्रकार is_transparentको सभी हीरा ऑपरेटरों के साथ जोड़ा गया था और नई कार्यक्षमता को इंगित करने के लिए टैग प्रकार के रूप में इस्तेमाल किया गया था जो कि सहयोगी कंटेनरों में सक्षम होना चाहिए। तकनीकी रूप से, कंटेनरों को "पारदर्शी फ़ंक्टर" की आवश्यकता नहीं है, बस एक है जो इसे विषम प्रकारों के साथ कॉल करने का समर्थन करता है (जैसे कि https://stackoverflow.com/a/18940595/981959pointer_comp में टाइप STL की परिभाषा के अनुसार पारदर्शी नहीं है)pointer_comp::is_transparentइसे समस्या को हल करने के लिए उपयोग करने की अनुमति देता है)। यदि आप कभी भी अपने std::set<T, C>प्रकार की कुंजियों के साथ देखते हैं Tया intफिर Cकेवल प्रकार के तर्कों के साथ कॉल करने की आवश्यकता होती है Tऔर int(किसी भी क्रम में), तो इसे वास्तव में पारदर्शी होने की आवश्यकता नहीं है। हमने उस नाम का आंशिक रूप से उपयोग किया क्योंकि हम एक बेहतर नाम के साथ नहीं आ सकते थे (मैं पसंद करूंगा is_polymorphicक्योंकि ऐसे फ़ंक्शंस में स्थैतिक बहुरूपता का उपयोग होता है, लेकिन पहले से ही एक std::is_polymorphicप्रकार का लक्षण है जो गतिशील बहुरूपता को संदर्भित करता है)।


3
अरे, क्या आप एक थे जिनसे एसटीएल ने कहा था, "निश्चित रूप से आप अपने सिर में टेम्प्लेट तर्क वितर्क कर सकते हैं" लिंक किए गए वूलस्टार में?
केरेक एसबी

10
नहीं, मैं वहां नहीं था, लेकिन मेरे सिर की तुलना में कहीं अधिक संकलित कंपाइलर वाले लोग हैं :)
जोनाथन वेकली

मुझे लगता है कि "डायमंड ऑपरेटर" <>लिंक किए गए प्रस्ताव में संदर्भित करता है , लेकिन उस प्रस्ताव ने परिचय नहीं दिया <>- यह एक खाली टेम्पलेट पैरामीटर सूची के लिए मौजूदा सिंटैक्स है। "डायमंड ऑपरेटर फ़ंक्शंस" थोड़ा कम भ्रामक होगा।
क्वाटर्ली

33

सी ++ 11 में वहाँ सदस्य टेम्पलेट्स नहीं कर रहे हैं find(), lower_bound()आदि है कि, कुछ भी इस परिवर्तन के कारण खो दिया है। सहयोगी कंटेनरों के साथ विषम कुंजी का उपयोग करने की अनुमति देने के लिए n3657 के साथ सदस्य टेम्पलेट पेश किए गए थे। मुझे कोई भी ठोस उदाहरण नहीं दिखाई देता है जहाँ यह उदाहरण के अलावा उपयोगी है जो अच्छा और बुरा है!

is_transparentउपयोग अवांछित रूपांतरण से बचने के लिए करना है। यदि सदस्य टेम्प्लेट असंबद्ध थे, तो मौजूदा कोड उन वस्तुओं से सीधे गुजर सकता है जिन्हें सदस्य टेम्प्लेट के बिना परिवर्तित किया गया होगा। N3657 से उदाहरण उपयोग-मामला std::set<std::string>एक स्ट्रिंग शाब्दिक का उपयोग करते हुए एक वस्तु का पता लगा रहा है : C ++ 11 परिभाषा के साथ एक std::stringवस्तु का निर्माण तब किया जाता है जब एक स्ट्रिंग शाब्दिक को संबंधित सदस्य फ़ंक्शन में पास किया जाता है। परिवर्तन के साथ सीधे स्ट्रिंग शाब्दिक का उपयोग करना संभव है। यदि अंतर्निहित तुलना फ़ंक्शन वस्तु को विशेष रूप से std::stringउस के संदर्भ में लागू किया जाता है, तो बुरा है क्योंकि अब std::stringप्रत्येक तुलना के लिए बनाया जाएगा। दूसरी ओर, यदि अंतर्निहित तुलना फ़ंक्शन ऑब्जेक्ट ए ले सकता हैstd::string और एक स्ट्रिंग शाब्दिक, जो अस्थायी वस्तु के निर्माण से बच सकता है।

is_transparentतुलनात्मक फ़ंक्शन ऑब्जेक्ट में नेस्टेड प्रकार निर्दिष्ट करने का एक तरीका प्रदान करता है कि क्या टेम्प्लेट किए गए सदस्य फ़ंक्शन का उपयोग किया जाना चाहिए: यदि तुलनात्मक फ़ंक्शन ऑब्जेक्ट विषम तर्कों से निपट सकता है, तो यह इस प्रकार को परिभाषित करता है कि यह विभिन्न तर्कों के साथ कुशलता से निपट सकता है। उदाहरण के लिए, नया ऑपरेटर फ़ंक्शन ऑब्जेक्ट्स को केवल operator<()पारदर्शी होने का दावा करता है। यह, कम से कम, काम करता है std::stringजिसके लिए char const*तर्क के रूप में लेने वाले ऑपरेटरों की तुलना में कम भार है। चूंकि ये फ़ंक्शन ऑब्जेक्ट्स नए भी हैं, भले ही वे गलत काम करते हैं (यानी किसी प्रकार के रूपांतरण की आवश्यकता होती है), कम से कम, एक मौन परिवर्तन नहीं होना चाहिए जिसके परिणामस्वरूप प्रदर्शन में गिरावट होती है।


धन्यवाद - अन्य प्रश्न पर मेरी टिप्पणी देखें: क्या आप डिफ़ॉल्ट रूप से पारदर्शी व्यवहार प्राप्त करते हैं?
केरेक एसबी

8
@KerrekSB: पारदर्शी व्यवहार सक्षम होता is_transparentहै जब 23.2.4 के अनुसार तुलनात्मक फ़ंक्शन ऑब्जेक्ट में परिभाषित किया जाता है [सहयोगी ।reqmts] पैराग्राफ 13. डिफ़ॉल्ट तुलना फ़ंक्शन ऑब्जेक्ट std::less<Key>23.4.2 [सहयोगी_मैप.syn] और 23.4 के अनुसार है। 3 [सहयोगी.सेट.साइन]। को 20.10.5 [तुलना] अनुच्छेद 4 सामान्य टेम्पलेट के अनुसार के लिए std::less<...>है नहीं एक नेस्टेड प्रकार को परिभाषित is_transparentलेकिन std::less<void>विशेषज्ञता है। यही है, नहीं, आपको डिफ़ॉल्ट रूप से एक पारदर्शी ऑपरेटर नहीं मिलता है।
डिटमार कुहल

क्या आपके पास नामकरण के लिए कोई विचार है? मेरा मतलब है क्यों is_transparent?
प्लाज़्माकेल

आप एक "ठोस उदाहरण चाहते हैं जहां यह उपयोगी हो"? यहाँ मेरा उपयोग मामला है
19 spraff

19

निम्नलिखित n3657 से सभी कॉपी-पास्ता है ।

Q. तुलनित्र को "पारदर्शी" बनाने का उद्देश्य क्या है?

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

Q. इससे क्या समस्या हल होती है

ए। LWG को निम्नलिखित के समान कोड के बारे में चिंता थी:

std::set<std::string> s = /* ... */;
s.find("key");

C ++ 11 में यह एक एकल std :: string अस्थायी का निर्माण करेगा और फिर इसे कुंजी खोजने के लिए तत्वों के साथ तुलना करेगा।

N3465 द्वारा प्रस्तावित परिवर्तन के साथ std :: set :: find () फ़ंक्शन एक असंबंधित टेम्प्लेट होगा जो तुलनित्र फ़ंक्शन, std :: कम के माध्यम से कॉन्स्टर्ड चार * पास करेगा, जो एक std :: string अस्थायी बनाएगा हर तुलना। LWG ने इस प्रदर्शन समस्या को एक गंभीर मुद्दा माना। टेम्पलेट खोज () फ़ंक्शन NULL को पॉइंटर्स कंटेनर में खोजने से भी रोकेगा, जो पहले मान्य कोड को अब संकलित करने का कारण बनता है, लेकिन इसे मूक प्रदर्शन प्रतिगमन की तुलना में कम गंभीर मुद्दे के रूप में देखा गया था

प्र। क्या यह बदलता है कि मानक कंटेनर कैसे काम करते हैं

A. यह प्रस्ताव सदस्य फ़ंक्शन टेम्प्लेट के साथ लुकअप सदस्य फ़ंक्शन को ओवरलोड करके और उसमें सहयोगी कंटेनरों को संशोधित करता है। कोई भाषा परिवर्तन नहीं हैं।

Q. तो क्या डिफॉल्ट सेट अपने सदस्यों, सदस्यों आदि को खोजने से चूक जाता है

A. लगभग सभी मौजूदा C ++ 11 कोड अप्रभावित हैं क्योंकि सदस्य फ़ंक्शन तब तक मौजूद नहीं हैं जब तक कि नए C ++ 14 पुस्तकालय सुविधाओं का उपयोग तुलना कार्यों के रूप में नहीं किया जाता है।

यक को कोट करने के लिए ,

C ++ 14 में, std :: set :: find एक टेम्पलेट फंक्शन है अगर तुलना करें तो is_transparent मौजूद है। जिस प्रकार से आप पास होते हैं, आपको कुंजी की जरूरत नहीं है, बस आपके तुलनित्र के बराबर है।

और n3657,

अनुच्छेद 13 को 23.2.4 में जोड़ें [सहयोगी.reqmts]: सदस्य फ़ंक्शन टेम्पलेट खोजते हैं, लोअरबाउंड, अपर_बाउंड और बराबर_रेंज ओवरलोड रिज़ॉल्यूशन में भाग नहीं लेंगे, जब तक कि प्रकार :: is_transparent मौजूद नहीं है।

n3421 "पारदर्शी ऑपरेटर फंडर्स" का एक उदाहरण प्रदान करता है ।

पूर्ण कोड यहाँ है


1
क्या std::set<std::string>वास्तव में "गुजरने वाले" से लाभ होता है char const *, या क्या आपको ए बनाने की आवश्यकता है std::set<std::string, std::less<>>?
केरेक एसबी

@ मुझे लगता है कि "चार कास्ट पास करना" समस्या थी जिससे बचने की कोशिश कर रहे थे, अगर मैं गलत नहीं हूँ। With the change proposed by N3465 the std::set::find() function would be an unconstrained template which would pass the const char* through to the comparator function, std::less<std::string>, which would construct a std::string temporary for every comparison. The LWG considered this performance problem to be a serious issue.

अनुच्छेद 13 के आपके उद्धरण और खदान विपरीत कहते हैं: "जब तक प्रकार मौजूद नहीं है / मौजूद नहीं है" ...?!
केरेक एसबी

4
@KerrekSB, यह मेरी गलती है, N3657 को "मौजूद" कहना चाहिए था, लेकिन मैंने लिखा "मौजूद नहीं है" ... यह आखिरी मिनट में लिखा गया एक देर से पेपर था। मसौदा मानक सही है।
योनातन वैखली

3
हां, यह उद्धृत करने के लिए स्पष्ट हो सकता है कि मेरे कहने का मतलब यह नहीं था कि मैंने वास्तव में उस समय क्या कहा था :)
जोनाथन वेकली

7

स्टेपहान टी लवजव उन समस्याओं के बारे में बात करते हैं जहां कंपाइलर अस्थायी रूप से निर्माण करता रहता है, और पारदर्शी ऑपरेटर फंक्शनलर्स का उनका प्रस्ताव कैसे इसे c ++ 1y में हल करेगा

GoingNative 2013 - संकलक (लगभग घंटे के निशान पर) की मदद न करें

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