इक्विटी ऑपरेटर को C ++ 20 में कस्टम स्पेसशिप ऑपरेटर कार्यान्वयन के लिए परिभाषित नहीं किया जाता है


51

मैं <=>C ++ 20 में नए स्पेसशिप ऑपरेटर के साथ एक अजीब व्यवहार कर रहा हूं । मैं विजुअल स्टूडियो 2019 कंपाइलर का उपयोग कर रहा हूं /std:c++latest

यह कोड ठीक संकलित करता है, जैसा कि अपेक्षित था:

#include <compare>

struct X
{
    int Dummy = 0;
    auto operator<=>(const X&) const = default; // Default implementation
};

int main()
{
    X a, b;

    a == b; // OK!

    return 0;
}

हालाँकि, अगर मैं X को इसमें बदलता हूँ :

struct X
{
    int Dummy = 0;
    auto operator<=>(const X& other) const
    {
        return Dummy <=> other.Dummy;
    }
};

मुझे निम्नलिखित संकलक त्रुटि मिलती है:

error C2676: binary '==': 'X' does not define this operator or a conversion to a type acceptable to the predefined operator

मैंने इसे क्लैंग पर भी आजमाया और मुझे भी ऐसा ही व्यवहार मिला।

मैं कुछ स्पष्टीकरण की सराहना करता हूं कि डिफ़ॉल्ट कार्यान्वयन operator==सही तरीके से क्यों उत्पन्न होता है, लेकिन कस्टम एक नहीं करता है।

जवाबों:


50

यह डिजाइन द्वारा है।

[class.compare.default] (जोर मेरा)

3 यदि वर्ग परिभाषा स्पष्ट रूप से == ऑपरेटर फ़ंक्शन की घोषणा नहीं करती है , लेकिन डिफ़ॉल्ट रूप से तीन-तरफ़ा तुलना ऑपरेटर फ़ंक्शन की घोषणा करती है, तो ऑपरेटर फ़ंक्शन को तीन-तरह की तुलना ऑपरेटर फ़ंक्शन ==के समान उपयोग के साथ घोषित किया जाता है। ==दसवीं कक्षा के लिए अनुमानित रूप से घोषित ऑपरेटर एक इनलाइन सदस्य है और इसे एक्स की परिभाषा में डिफ़ॉल्ट रूप से परिभाषित किया गया है।

केवल एक डिफ़ॉल्ट रूप से <=>संश्लेषित ==करने की अनुमति देता है। तर्क यह है कि वर्गों जैसे std::vectorएक डिफ़ॉल्ट का उपयोग नहीं कर सकते हैं <=>। इसके अलावा, वैक्टर की तुलना करने के <=>लिए उपयोग ==करना सबसे कुशल तरीका नहीं है। <=>सटीक क्रम देना चाहिए, जबकि ==पहले आकार की तुलना करके जल्दी जमानत हो सकती है।

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


4
यह निश्चित रूप से समझदार है, जब तक कि अंतरिक्ष यान छोटी गाड़ी नहीं है। संभावित रूप से घोर अक्षम्य हालांकि ...
Deduplicator

1
@ डिड्यूप्लिकेटर - संवेदनशीलता व्यक्तिपरक है। कुछ कहेंगे कि चुपचाप उत्पन्न अक्षम्य कार्यान्वयन समझदारी नहीं है।
स्टोरीटेलर - अनसलैंडर मोनिका

45

इस सुविधा के मानकीकरण के दौरान, यह निर्णय लिया गया था कि समानता और आदेश को तार्किक रूप से अलग किया जाना चाहिए। जैसे, समानता परीक्षण (का उपयोग करता है ==और !=) होगा कभी नहीं आह्वान operator<=>। हालाँकि, यह तब भी उपयोगी था जब दोनों एक ही घोषणा के साथ दोनों को डिफ़ॉल्ट करने में सक्षम थे। इसलिए यदि आप डिफॉल्ट करते हैं operator<=>, तो यह निर्णय लिया गया कि आप भी डिफॉल्ट करने के लिए हैं operator==(जब तक कि आप इसे बाद में परिभाषित नहीं करते हैं या पहले इसे परिभाषित नहीं करते हैं)।

जैसा कि यह निर्णय क्यों किया गया था , मूल तर्क इस तरह से होता है। विचार करें std::string। दो तारों का आदेश शाब्दिक है; प्रत्येक वर्ण के दूसरे स्ट्रिंग में प्रत्येक वर्ण के मुकाबले इसका पूर्णांक मान होता है। आदेश देने के परिणाम में पहली असमानता है।

हालांकि, स्ट्रिंग्स के समानता परीक्षण में शॉर्ट-सर्किट होता है। यदि दो तार बराबर लंबाई के नहीं हैं, तो चरित्र-वार तुलना करने का कोई मतलब नहीं है; वे बराबर नहीं हैं। इसलिए अगर कोई समानता परीक्षण कर रहा है, तो आप इसे लंबे समय तक नहीं करना चाहते हैं यदि आप इसे शॉर्ट-सर्किट कर सकते हैं।

यह पता चला है कि उपयोगकर्ता-परिभाषित आदेश की आवश्यकता वाले कई प्रकार भी समानता परीक्षण के लिए कुछ शॉर्ट-सर्किट तंत्र की पेशकश करेंगे। लोगों को केवल लागू करने operator<=>और संभावित प्रदर्शन को फेंकने से रोकने के लिए , हम प्रभावी रूप से सभी को दोनों करने के लिए मजबूर करते हैं।


5
स्वीकृत उत्तर की तुलना में यह बहुत बेहतर व्याख्या है
मेमो

17

अन्य उत्तर वास्तव में अच्छी तरह से समझाते हैं कि भाषा इस तरह क्यों है। मैं बस यह जोड़ना चाहता था कि यदि यह स्पष्ट नहीं है, तो यह निश्चित रूप से एक उपयोगकर्ता-प्रदान के operator<=>साथ डिफ़ॉल्ट रूप से संभव है operator==। आपको बस डिफ़ॉल्ट रूप से स्पष्ट रूप से लिखना होगा operator==:

struct X
{
    int Dummy = 0;
    auto operator<=>(const X& other) const
    {
        return Dummy <=> other.Dummy;
    }
    bool operator==(const X& other) const = default;
};
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.