Libc ++ का वेक्टर <bool> :: const_reference bool क्यों नहीं है?


92

धारा 23.3.7 वर्ग vector<bool>[वेक्टर.बूल], पैरा 1 राज्य:

template <class Allocator> class vector<bool, Allocator> {
public:
    // types:
    typedef bool              const_reference;
    ...

हालांकि यह प्रोग्राम libc ++ का उपयोग करते समय संकलित करने में विफल रहता है:

#include <vector>
#include <type_traits>

int
main()
{
    static_assert(std::is_same<std::vector<bool>::const_reference, bool>{}, "?");
}

इसके अलावा, मैं ध्यान देता हूं कि C ++ मानक C विनिर्देशन के सभी तरह से C ++ 98 पर वापस आ चुका है। और मैं आगे ध्यान देता हूं कि libc ++ ने पहली बार libc ++ की शुरूआत के बाद से लगातार इस विनिर्देश का पालन नहीं किया है।

इस गैर-अनुरूपता के लिए प्रेरणा क्या है?

जवाबों:


99

इस विस्तार के लिए प्रेरणा, जो एक अनुरूप कार्यक्रम द्वारा पता लगाने योग्य है, और इस प्रकार गैर-अनुरूप है vector<bool>vector<char> संदर्भों के संबंध में अधिक व्यवहार करना है (कास्ट और अन्यथा)।

परिचय

1998 के बाद से, vector<bool>"काफी कंटेनर नहीं है।" LWG 96 , पहले LWG मुद्दों में से एक, ने बहस शुरू की। आज, 17 साल बाद,vector<bool> काफी हद तक अपरिवर्तित है।

यह पेपर कुछ विशिष्ट उदाहरणों पर जाता है कि किस तरह से व्यवहार vector<bool>हर दूसरे के तात्कालिकता से भिन्न होता है vector, इस प्रकार सामान्य कोड को नुकसान पहुंचा रहा है। हालांकि एक ही कागज की लंबाई बहुत अच्छे प्रदर्शन गुणों पर चर्चा करती हैvector<bool> अगर ठीक से लागू किया जा सकता है।

सारांश : vector<bool> एक बुरा कंटेनर नहीं है। यह वास्तव में काफी उपयोगी है। इसका सिर्फ एक बुरा नाम है।

वापस const_reference

जैसा कि ऊपर प्रस्तुत किया गया है, और यहां विस्तृत है , इसके बारे vector<bool>में क्या बुरा है कि यह अन्य vectorतात्कालिकताओं की तुलना में सामान्य कोड में अलग तरह से व्यवहार करता है। यहाँ एक ठोस उदाहरण दिया गया है:

#include <cassert>
#include <vector>

template <class T>
void
test(std::vector<T>& v)
{
    using const_ref = typename std::vector<T>::const_reference;
    const std::vector<T>& cv = v;
    const_ref cr = cv[0];
    assert(cr == cv[0]);
    v[0] = 1;
    assert(true == cv[0]);
    assert(cr == cv[0]);  // Fires!
}

int
main()
{
    std::vector<char> vc(1);
    test(vc);
    std::vector<bool> vb(1);
    test(vb);
}

मानक विनिर्देश कहता है कि चिह्नित किया गया चिह्न // Fires!ट्रिगर हो जाएगा, लेकिन केवल जब testएक के साथ चलाया जाता है vector<bool>। जब एक vector<char>(या vectorइसके अलावा किसी boolउपयुक्त गैर-डिफ़ॉल्ट Tअसाइन किए जाने पर) के साथ चलाया जाता है , तो परीक्षण गुजरता है।

vector<bool>जेनेरिक कोड में अलग तरह से व्यवहार करने के नकारात्मक प्रभावों को कम करने के लिए मांगी गई libc ++ कार्यान्वयन । इसे प्राप्त करने के लिए एक बात यह है कि निर्दिष्ट के समान vector<T>::const_referenceएक प्रॉक्सी-संदर्भ बनाना है vector<T>::reference, सिवाय इसके कि आप इसके माध्यम से असाइन नहीं कर सकते। यानी, libc ++ पर,vector<T>::const_reference अनिवार्य रूप से उस बिट vectorकी एक कॉपी के बजाय, अंदर के बिट के लिए एक पॉइंटर है ।

Libc ++ पर उपरोक्त testदोनों के लिए गुजरता है vector<char>और vector<bool>

किस कीमत पर?

नकारात्मक पक्ष यह है कि यह विस्तार पता लगाने योग्य है, जैसा कि प्रश्न में दिखाया गया है। हालांकि, बहुत कम प्रोग्राम वास्तव में इस उपनाम के सटीक प्रकार के बारे में परवाह करते हैं, और अधिक कार्यक्रम व्यवहार के बारे में परवाह करते हैं।

इस गैर-अनुरूपता के लिए प्रेरणा क्या है?

जेनेरिक कोड में libc ++ क्लाइंट को बेहतर व्यवहार देने के लिए, और शायद पर्याप्त फ़ील्ड परीक्षण के बाद, इस एक्सटेंशन को भविष्य के C ++ मानक के लिए पूरे C ++ उद्योग की बेहतरी के लिए प्रस्तावित करें।

इस तरह का प्रस्ताव एक नए कंटेनर (जैसे bit_vector) के रूप में आ सकता है vector<bool>, जिसमें आज के समान ही एपीआई है , लेकिन कुछ उन्नयन जैसे कि const_referenceयहां चर्चा की गई है। vector<bool>विशेषज्ञता के पदावनति (और अंतिम निष्कासन) के बाद । bitsetइस विभाग में थोड़ा उन्नयन का उपयोग भी कर सकता है, उदाहरण के लिए const_reference, और पुनरावृत्तियों का एक सेट।

यही है, के लिए hindsight bitsetमें है vector<bool>(जिसे bit_vector- या जो भी नाम दिया जाना चाहिए ), जैसा arrayकि है vector। और सादृश्य सच धारण करने के लिए किया जाए या नहीं के बारे में हम बात कर रहे हैं चाहिए boolके रूप में value_typeकी vectorऔर array

C ++ 11 और C ++ 14 सुविधाओं के कई उदाहरण हैं जो libc ++ में एक्सटेंशन के रूप में शुरू हुए हैं। इस तरह मानकों का विकास होता है। वास्तविक रूप से प्रदर्शित सकारात्मक क्षेत्र अनुभव मजबूत प्रभाव को वहन करता है। जब यह मौजूदा विनिर्देशों को बदलने की बात आती है तो मानक लोक एक रूढ़िवादी गुच्छा होते हैं (जैसा कि उन्हें होना चाहिए)। अनुमान लगाना, यहां तक ​​कि जब आप सुनिश्चित हैं कि आप सही ढंग से अनुमान लगा रहे हैं, तो अंतरराष्ट्रीय स्तर पर मान्यता प्राप्त मानक विकसित करने के लिए एक जोखिम भरा रणनीति है।


1
प्रश्न: @EricNiebler द्वारा प्रॉक्सी पुनरावृत्तियों पर हाल ही में मसौदा प्रस्ताव किसी भी तरह से libc ++ एक्सटेंशन को वैध कर सकता है और vector<bool>अधिक प्रथम श्रेणी के पायदान पर रख सकता है ?
TemplateRex

टिप्पणी: मैं एक कराना पसंद करते हैं vector_bool<Alloc>और एक array_bool<N>पैक संस्करणों में से (यादृच्छिक अभिगम प्रॉक्सी सभी बिट्स पुनरावृत्ति iterators सहित) का प्रतिनिधित्व करने vector<bool, Alloc>और array<bool, N>। हालांकि, bitset<N>(और यह चचेरा भाई है boost::dynamic_bitset<Alloc>) एक अलग अमूर्त का प्रतिनिधित्व करता है: अर्थात् के पैक्ड संस्करण std::set<int>। इसलिए मैं, है कहते हैं, चाहते हैं bit_array<N>और bit_vector<Alloc>bitset मताधिकार के उत्तराधिकारी, उचित साथ रहने के लिए द्विदिश iterators (के बजाय सभी बिट्स से अधिक 1-बिट से अधिक पुनरावृत्ति)। इस पर आपके विचार क्या हैं?
टेम्प्लेट

5
प्रॉक्सी पुनरावृत्तियों पर मेरा मसौदा प्रस्ताव vector<bool>एक एसटीडी-अनुरूप रैंडम-एक्सेस कंटेनर बना देगा। यह vector<bool>एक अच्छा विचार नहीं होगा । :-) मैं हावर्ड से सहमत हूँ। इसे कुछ और कहा जाना चाहिए था।
एरिक नीब्लर

1
लिबास ++ एक्सटेंशन से बाहर निकलने और कड़ाई से अनुरूप व्यवहार करने का एक तरीका क्यों नहीं है? (मैं कंफर्ट को डिफॉल्ट बनाने के लिए भी नहीं कह रहा हूं, पोर्टेबल कोड लिखने में सक्षम होने के लिए libc ++ के एक्सटेंशन को अक्षम करने का एक तरीका है)। जैसा कि आप जानते हैं कि मुझे पिछले दिनों libc ++ tuple एक्सटेंशन द्वारा काट लिया गया था, और हाल ही में बिटसेट :: const_ferference एक्सटेंशन द्वारा काट लिया गया था।
gnzlbg

5
@gnzlbg: libc ++ के प्रारंभिक विकास के लिए आर्थिक और अस्थायी संसाधन उपलब्ध थे। इसके बाद कार्यान्वयन को हर एक उपयोगकर्ता को खुश नहीं करने के लिए बर्बाद किया गया था। उपलब्ध संसाधनों को देखते हुए, इंजीनियरिंग ट्रेडऑफ़ को खुश उपयोगकर्ताओं की संख्या को अधिकतम करने के प्रयास में बनाया गया था, जो समग्र सी ++ समुदाय को अधिकतम लाभ पहुंचाता है। आपके अनुभव के बारे में क्षमा करें। मैं ध्यान देता हूं कि आपके द्वारा चलाए गए टूपल एक्सटेंशन वर्तमान C ++ 1z वर्किंग पेपर में हैं। उस मुद्दे पर, आपने अनजाने में बलिदान कर दिया ताकि बहुतों को फायदा हो सके, और उन पर आपका बहुत-बहुत आभार हो।
हावर्ड हिनान्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.