2012-08-04 5 views
9

§21.4.5 [string.access]एक std :: स्ट्रिंग कार्यान्वयन अनुरूप है जहां 's.c_str() + s.size()' जरूरी नहीं है '& s [s.size()]'?

const_reference operator[](size_type pos) const; 
reference operator[](size_type pos); 

रिटर्न:*(begin() + pos) अगर pos < size()। अन्यथा, charT के प्रकार charT() के साथ किसी ऑब्जेक्ट का संदर्भ देता है, जहां ऑब्जेक्ट को संशोधित करने से अपरिभाषित व्यवहार होता है।

दूसरे भाग का तात्पर्य मुझे कम से कम करने के लिए, कि यह "प्रकार charT की वस्तु" अनुक्रम std::string वस्तु में संग्रहीत के बाहर रहते हैं हो सकता है। एक अनुरूप operator[] का उदाहरण कार्यान्वयन:

reference operator[](size_type pos){ 
    static contexpr charT default = charT(); 
    if(pos == size()) 
    return default; 
    return buf[pos]; 
} 

अब, c_str()/data(), operator[] के मामले में निर्दिष्ट कर रहे हैं:

§21.4.7 [string.accessors]

const charT* c_str() const noexcept; 
const charT* data() const noexcept; 

रिटर्न: एक संकेतक p ऐसा है कि प्रत्येकके लिए p + i == &operator[](i)[0,size()] में।

इससे ऊपर operator[] कार्यान्वयन गैर-अनुरूप होगा, p + size() != &operator[](size()) के रूप में। हालांकि, प्रवंचना का एक सा के साथ, आप इस समस्या को दरकिनार कर सकते हैं:

reference operator[](size_type pos){ 
    static contexpr charT default = charT(); 
    if(pos == size() && !evil_context) // assume 'volatile bool evil_context;' 
    return default; 
    return buf[pos]; 
} 

struct evil_context_guard{ 
    volatile bool& ctx; 
    evil_context_guard(volatile bool& b) 
    : ctx(b) {} 
    ~evil_context_guard(){ b = false; } 
}; 

const charT* c_str() const noexcept{ 
    evil_context_guard g(evil_context = true); 
    // now, during the call to 'c_str()', the requirement above holds 
    // 'p + i == &operator[](i) for each i in [0,size()]' 
    const charT* p = &buf[0]; 
    assert(p+size() == &operator[](size())); 
    return p; 
} 

अब, स्पष्ट सवाल यह है कि ...

ऊपर कोड वास्तव में अनुरूप है या मैं कुछ को नजरअंदाज किया?

+0

एक बात मुझे पता है कि यदि आप वास्तव में एक स्ट्रिंग ऑब्जेक्ट 'str' के लिए चेक आउट लिखते थे: 'char * p = str.c_str(); size_t i = str.size(); जोर दें (पी + i == और str [i]); 'आपके कोड के साथ दावा विफल हो जाएगा। मानक एक विशिष्ट संदर्भ निर्दिष्ट नहीं करता है जहां invariant को पकड़ना चाहिए, इसलिए मैं यह मानने के बारे में सावधान रहूंगा कि इसे केवल 'c_str() 'रिटर्न से पहले पकड़ना होगा। – pmdj

उत्तर

4

दिया कोड की अनदेखी करते हुए केवल सवाल पर विचार, मुझे लगता है कि

  • दुर्भाग्य से, इस सवाल का जवाब “ हाँ ”, और
  • निश्चित रूप से है कि आशय मानक के नहीं हो रहा है ।

इसलिए, यह दोष प्रतीत होता है।

list of known library defects की जांच कर रहा है जाहिर है कि इस मुद्दे की अभी तक रिपोर्ट नहीं की गई है।

तो, के रूप में मैं बातचीत में कहा गया है, मैं इसे [comp.std.C++] पर पोस्ट करने की सलाह देते हैं, ताकि चाहे वह वास्तव में एक दोष है के सवाल हल करने के लिए, और यदि ऐसा है तो, इसे में प्राप्त करने के लिए दोष सूची और तय।

+4

मुझे एक अस्पष्ट संदेह है कि यह जानबूझकर है। यह शब्द किसी भी 'स्थैतिक चार' का उपयोग करके खाली तारों को प्रदर्शित करने की अनुमति देता है (इस शब्द के बिना, नल बाइट प्रत्येक स्ट्रिंग के लिए अद्वितीय होना चाहिए, जिसके लिए या तो (1) रिक्त तारों को इन-ऑब्जेक्ट का उपयोग करके प्रदर्शित किया जाना चाहिए नल-बाइट, या (2) गतिशील आवंटित बफर की आवश्यकता होती है)। मुझे यकीन नहीं है कि यह (1) से बेहतर क्यों होगा, लेकिन यह एक अजीब संयोग है कि यह शब्द इसे संभव बनाता है, इसलिए मुझे लगता है कि यह जानबूझकर – jalf

+0

@jalf: एसएसओ के पास गतिशील स्मृति आवंटन के बिना छोटे तार हैं। यह इस शून्य बाइट के लिए बिल्कुल सही होगा, इसलिए मुझे नहीं पता कि यह एक मुद्दा कैसे होगा। क्या आप समझाएंगे? –

+1

@Maththieu: लेकिन एसएसओ अनिवार्य नहीं है? – ildjarn

0

मुझे नहीं लगता कि यह अनुरूप कैसे हो सकता है। उपयोगकर्ता कोड कभी भी वादा किए गए लौटे मूल्य का निरीक्षण नहीं कर सकता है।कोड में assert भ्रामक है क्योंकि यह गलत जगह पर है: फ़ंक्शन अभी तक वापस नहीं आया है। रिटर्न: आवश्यकताएं फ़ंक्शन से लौटाई गई मान पर लागू होती हैं, न कि इसके कार्यान्वयन के भीतर कुछ मूल्य (यह स्पष्ट होना चाहिए कि यह एक गैरकानूनी विचार क्यों है)।

अभिकथन यहाँ होना चाहिए:

auto p = s.c_str(); 
assert(p + s.size() == &operator[](s.size())); 

मेरा मानना ​​है कि शब्दों है कि s[s.size()] विशेष रूप से व्यवहार करता है बस अशक्त टर्मिनेटर उड़ा से आप ना करे के लिए है।

+0

मुझे नल-टर्मिनेटर को उड़ाने से रोकने के लिए, वे सिर्फ इतना कह सकते थे कि "s [s.size()] 'संदर्भित मान को संशोधित न करें और इस विशिष्ट मान को अस्तित्व में रखने की अनुमति नहीं देनी होगी अनुक्रम के बाहर। – Xeo

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