एसटीडी क्यों नहीं करता है :: क्लैंग / विन के तहत वेक्टर <बूल> तत्वों पर स्वैप काम?


14

मेरे पास इस तरह का कोड है:

#include <vector>
#include <utility>

int main()
{
   std::vector<bool> vb{true, false};
   std::swap(vb[0], vb[1]);
}

vector<bool>एक तरफ की पवित्रता के बारे में तर्क , यह ठीक काम कर रहा था:

  • मैक के लिए क्लैंग
  • विंडोज के लिए विजुअल स्टूडियो
  • लिनक्स के लिए जीसीसी

फिर मैंने इसे विंडोज़ पर क्लैंग के साथ बनाने की कोशिश की और निम्नलिखित त्रुटि प्राप्त की (संक्षिप्त):

error: no matching function for call to 'swap'
                                std::swap(vb[0], vb[1]);
                                ^~~~~~~~~

note: candidate function [with _Ty = std::_Vb_reference<std::_Wrap_alloc<std::allocator<unsigned int> > >, $1 = void] not viable: expects an l-value for 1st argument
inline void swap(_Ty& _Left, _Ty& _Right) _NOEXCEPT_COND(is_nothrow_move_constructible_v<_Ty>&&

मुझे आश्चर्य है कि परिणाम पूरे कार्यान्वयन में भिन्न हैं।

यह विंडोज पर क्लैंग के साथ काम क्यों नहीं करता है?


इसलिए मुझे लगता है कि स्पष्टीकरण की आवश्यकता है: क्या operator[]एक अंतराल का परिणाम है ? और std::swaprvalues ​​और xvalues ​​पर काम कर सकते हैं?
Mgetz

@Mgetz हाँ। उस क्रम में नहीं। इस सवाल को दूसरे दिन निजी तौर पर "वास्तविक" के लिए पूछा गया था, और मैंने इसे पर्याप्त रूप से मनोरंजक समझा कि जवाब "क्लैंग / विन टूटा नहीं है, कोड इस पूरे समय टूट गया था लेकिन मुख्यधारा के टूलकिन कॉम्बो ने आपको कभी भी परेशान नहीं किया; "इसे यहाँ लिखने के लिए: P
लाइटनेस दौड़ Orbit

2
एक FYI के रूप में, यह वीएस 2019 में /permissive-(अनुरूपता) के साथ संकलित नहीं करता है , जिसे आम तौर पर किसी भी तरह से उपयोग किया जाना चाहिए;)
क्रिसम

1
@ChrisMM वास्तव में! अनुरूप मोड बंद पहेली का एक हिस्सा था। (हालांकि हमें नहीं पता था कि इसे देखने से पहले!) और मेरा जवाब यह बताता है कि: P
लाइटनेस दौड़ ऑर्बिट

जवाबों:


15

मानक को किसी टूलकिन पर संकलन करने की आवश्यकता नहीं होती है !

पहले याद रखें कि vector<bool>यह अजीब है और इसे कम करने से आपको एक std::vector<bool>::referenceवास्तविक के बजाय एक प्रॉक्सी प्रकार की अस्थायी वस्तु मिलती है , जिसे कॉल किया जाता है bool&

त्रुटि संदेश आपको बता रहा है कि यह इस अस्थायी को constजेनेरिक template <typename T> std::swap(T& lhs, T& rhs)कार्यान्वयन में गैर- लंबित संदर्भ से बाँध नहीं सकता है।

एक्सटेंशन!

हालांकि, यह पता चला है कि libstdc ++ एक अधिभार को परिभाषित करता है के लिए std::swap(std::vector<bool>::reference, std::vector<bool>::reference)है, लेकिन इस मानक के लिए एक विस्तार है (या, अगर यह वहाँ में है, मैं इसके लिए कोई सबूत नहीं मिल सकता है)।

libc ++ ऐसा भी करता है

मुझे लगता है कि विजुअल स्टूडियो stdlib कार्यान्वयन, जिसे आप अभी भी उपयोग कर रहे हैं, नहीं करता है , लेकिन फिर चोट के अपमान को जोड़ने के लिए आप अस्थायी वीएस में संदर्भों को रोक सकते हैं (जब तक कि आप अनुरूपता मोड का उपयोग नहीं कर रहे हैं), इसलिए मानक, "जेनेरिक", std::swapफ़ंक्शन तब तक काम करता है जब तक आप स्ट्रिकटर क्लैंग कंपाइलर के लिए वीएस कंपाइलर का विकल्प नहीं देते।

नतीजतन, आप उन सभी टूलकिन्स के एक्सटेंशन पर भरोसा कर रहे हैं जिनके लिए यह आपके लिए काम करता था, और विंडोज संयोजन पर क्लैंग एकमात्र ऐसा है जो वास्तव में सख्त अनुपालन का प्रदर्शन कर रहा है।

(मेरी राय में, उन तीन टूलचाइन्स को इसका निदान करना चाहिए था ताकि आपने इस पूरे समय में गैर-पोर्टेबल कोड को जहाज न किया हो।)

अब क्या?

यह की अपनी विशेषज्ञता को जोड़ने के लिए आकर्षक हो सकता है std::swapऔर std::vector<bool>::reference, लेकिन आप मानक प्रकार के लिए ऐसा करने की अनुमति नहीं कर रहे हैं; वास्तव में, यह अतिभार के साथ संघर्ष करेगा जो libstdc ++ और libc ++ ने एक्सटेंशन के रूप में जोड़ने के लिए चुना है।

तो, पोर्टेबल और आज्ञाकारी होने के लिए, आपको अपना कोड बदलना चाहिए

शायद एक अच्छे पुराने जमाने का:

const bool temp = vb[0];
vb[0] = vb[1];
vb[1] = temp;

या विशेष स्थिर सदस्य फ़ंक्शन का उपयोग करें जो वास्तव में आप चाहते थे :

std::vector<bool>::swap(vb[0], vb[1]);

इस प्रकार वर्तनी भी:

vb.swap(vb[0], vb[1]);

लेकिन एएफएआईके के संबंध में ऐसा नहीं है कि उन्हें ऐसा करने की अनुमति है। जब तक वे अनुरूप कोड नहीं तोड़ते वे टूटे हुए कोड को "ओके" करने के लिए कार्यान्वयन का विस्तार कर सकते हैं।
नाथनऑलिवर

@ NathanOliver-ReinstateMonica खैर, ठीक है। क्या उन्हें कम से कम ऐसी चीजों के उपयोग का निदान नहीं करना है, हालांकि? eel.is/c++draft/intro.compliance#8
कक्षा में

@LightnessRaceswithMonica क्या कोई भाषा है जो इस विस्तार को मना करती है?
Mgetz

@Mgetz क्षमा करें, मैं सभी मौजूदा भाषाओं में वार्तालाप नहीं कर रहा हूँ, इसलिए मैं इसका उत्तर नहीं दे सकता
कक्षा

मुझे यकीन नहीं है कि इस तरह के एक्सटेंशन का उपयोग किया जाता है जो इस दस्तावेज़ के अनुसार बीमार हैं । उन्होंने एक अधिभार जोड़ा जो कि std::vector<bool>::referenceकुछ भी नहीं लेता है वास्तव में बीमार है। मेरे लिए यह ऐसा लगता है जैसे कुछ का उपयोग करने के लिए char * foo = "bar";निदान की आवश्यकता होती है क्योंकि यह बीमार है।
नाथनऑलिवर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.