c++ - फंक्शन रोकना const std:: string & accept 0 से




implicit-conversion (2)

एक विकल्प operator[]() private अधिभार को घोषित करना है operator[]() जो एक अभिन्न तर्क को स्वीकार करता है, और इसे परिभाषित नहीं करता है।

यह विकल्प void operator[](std::nullptr_t) = delete जैसे विकल्पों के विपरीत सभी C ++ मानकों (1998 पर) के साथ काम करेगा, जो C ++ 11 से मान्य हैं।

operator[]() को private सदस्य बनाने से आपके उदाहरण पर कोई त्रुटि नहीं होगी, जब तक कि उस अभिव्यक्ति का उपयोग कक्षा के किसी सदस्य या friend द्वारा नहीं किया जाता है।

यदि उस अभिव्यक्ति का उपयोग किसी सदस्य फ़ंक्शन या कक्षा के friend से किया जाता है, तो कोड संकलन करेगा - लेकिन फ़ंक्शन परिभाषित नहीं होने के कारण - आम तौर पर बिल्ड विफल हो जाएगा (जैसे एक अपरिभाषित फ़ंक्शन के कारण लिंकर त्रुटि)।

एक हजार शब्दों के लायक:

#include<string>
#include<iostream>

class SayWhat {
    public:
    SayWhat& operator[](const std::string& s) {
        std::cout<<"here\n"; // To make sure we fail on function entry
        std::cout<<s<<"\n";
        return *this;
    }
};

int main() {
    SayWhat ohNo;
    // ohNo[1]; // Does not compile. Logic prevails.
    ohNo[0]; // you didn't! this compiles.
    return 0;
}

संकलक 0 को पास करने पर शिकायत नहीं कर रहा है ताकि ब्रैकेट संचालक स्ट्रिंग को स्वीकार कर सके। इसके बजाय, यह विधि के साथ प्रवेश करने से पहले संकलित करता है और विफल रहता है:

terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_S_construct null not valid

सन्दर्भ के लिए:

> g++ -std=c++17 -O3 -Wall -Werror -pedantic test.cpp -o test && ./test
> g++ --version
gcc version 7.3.1 20180303 (Red Hat 7.3.1-5) (GCC)

मेरा अनुमान

संकलक निहित है std::string(0) कंस्ट्रक्टर का उपयोग विधि में प्रवेश करने के लिए, जो बिना किसी अच्छे कारण के एक ही समस्या (उपरोक्त त्रुटि को गूगल करता है) पैदा करता है।

सवाल

क्या कक्षा की ओर से इसे ठीक करने के लिए कुछ भी है, इसलिए एपीआई उपयोगकर्ता को यह महसूस नहीं होता है और संकलन समय पर त्रुटि का पता लगाया जाता है?

यही है, एक अधिभार जोड़ना

void operator[](size_t t) {
    throw std::runtime_error("don't");
}

एक अच्छा समाधान नहीं है।


कारण std::string(0) वैध है, 0 कारण एक null पॉइंटर स्थिर है। तो यह एक पॉइंटर लेने वाले कंस्ट्रक्टर से मेल खाता है। तब यह पूर्व शर्त से चलता है कि कोई nd पॉइंटर को std::string पास नहीं कर सकता है। केवल शाब्दिक 0 व्याख्या एक अशक्त सूचक स्थिरांक के रूप में की जाएगी, अगर यह int में रन टाइम वैल्यू था तो आपको यह समस्या नहीं होगी (क्योंकि तब अधिभार संकल्प इसके बजाय एक int रूपांतरण की तलाश में होगा)। न ही शाब्दिक 1 एक समस्या है, क्योंकि 1 शून्य सूचक स्थिर नहीं है।

चूंकि यह एक संकलन समय समस्या है (शाब्दिक अमान्य मूल्य) आप इसे संकलन समय पर पकड़ सकते हैं। इस फॉर्म का एक अधिभार जोड़ें:

void operator[](std::nullptr_t) = delete;

std::nullptr_t का प्रकार है। और यह किसी भी null पॉइंटर 0ULL , यह 0 , 0ULL , या nullptr । और चूंकि फ़ंक्शन हटा दिया गया है, यह अधिभार संकल्प के दौरान एक संकलन समय त्रुटि का कारण होगा।







implicit-conversion