अयोग्य प्रकार () - जब यह std :: वेक्टर पर उपयोग किया जाता है और std :: array पर उपयोग नहीं किया जाता है, और कौन सा संकलक सही है?


11

जब बुला std::sort()एक पर std::array:

#include <vector>
#include <array>
#include <algorithm>

int main() {
    std::vector<int> foo{4, 1, 2, 3};
    sort(begin(foo), end(foo));

    std::array<int, 4> foo2{4, 1, 2, 3};
    sort(begin(foo2), end(foo2));
}

जीसीसी और क्लैंग दोनों एक त्रुटि को इस तरह से लौटाते std::arrayहैं - क्लैंग कहते हैं

त्रुटि: अघोषित पहचानकर्ता 'सॉर्ट' का उपयोग; क्या आपका मतलब था 'एसटीडी :: सॉर्ट'?

std::sort(begin(foo2), end(foo2))समस्या को ठीक करने के लिए बदल रहा है।

MSVC उपरोक्त कोड को लिखित रूप में संकलित करता है।

क्यों के बीच इलाज में अंतर std::vectorऔर std::array; और कौन सा संकलक सही है?


sort(...-> std::sort(...। मुझे लगता है कि ADL (तर्क पर निर्भर लुकअप) है जो आपको ट्रिप कर रहा है। वह, या कटौती गाइड। किसी भी स्थिति में; आपके द्वारा कॉल किए जाने वाले कार्यों को हमेशा योग्य बनाएं।
जेसपर जुहल

3
यह हो सकता है कि MSVC लाइब्रेरी में कुछ विशेषज्ञता है std::sortजो तर्क-निर्भर लुकअप की ओर जाता है (जैसे आपके पास पहले से है std::beginऔर std::end)?
कुछ प्रोग्रामर

1
@Someprogrammerdude यह सीधे तौर पर वीसी ++ के stdlib उपयोग के सभी प्रकार के श्रेणी प्रकार पुनरावृत्तियों को परिभाषित करता है namespace std, जहां एक साधारण सूचक प्रकार काम करता है। मेरा मानना ​​है कि यह ओवररन और अन्य सामान्य त्रुटियों का पता लगाने के लिए डिबग-बिल्ड चेक सम्मिलित करना है।
फ्रैंकोइस एंड्रीक्स

जवाबों:


16

इस प्रकार के लिए नीचे आता है जाता है कि beginऔर endपरिणाम के लिए और कैसे के साथ काम करता है कि तर्क आश्रित लुक

में

sort(begin(foo), end(foo));

आपको मिला

sort(std::vector<int>::iterator, std::vector<int>::iterator)

और चूँकि ADL std::vector<int>::iteratorका एक सदस्य stdपाता sortहै stdऔर कॉल सफल होता है।

साथ में

sort(begin(foo2), end(foo2));

आपको मिला

sort(int*, int*)

और क्योंकि int*कोई सदस्य नहीं है std, ADL में नहीं दिखेगा stdऔर आप नहीं पा सकते हैं std::sort

यह MSVC में काम करता है क्योंकि

sort(begin(foo2), end(foo2));

हो जाता है

sort(std::_Array_iterator, std::_Array_iterator)

और चूंकि ADL std::_Array_iteratorका हिस्सा stdहै sort

दोनों कंपाइलर इस व्यवहार के साथ सही हैं। std::vectorऔर इट्रेटर केstd::array लिए किस प्रकार का उपयोग किया जाता है, इसकी कोई आवश्यकता नहीं है, सिवाय इसके कि यह LegacyRandomAccessIterator आवश्यकता को पूरा करता है और इसके लिए C ++ 17 में std::arrayवह प्रकार भी एक लिटरल टाइप हो सकता है और C ++ 20 में कि यह एक कांस्टीट्यूएंटर हो सकता है


1
मुझे लगता है कि सवाल MSVC के व्यवहार के अनुरूप है, यानी करता है कि क्या है std::arrayइटरेटर है होना करने के लिए int*या यह एक वर्ग प्रकार हो सकता है? इसी तरह std::vectorयह इस सवाल के लिए प्रासंगिक होगा कि क्या इट्रेटर को एक वर्ग प्रकार होना चाहिए जिस पर एडीएल काम करेगा, या क्या यह भी हो सकता है int*
अखरोट

@ मेवात यह हो सकता है कि जो कुछ भी क्रियान्वयन करना चाहता है। यह एक std::iterator, कुछ और, या सिर्फ एक संकेतक हो सकता है।
नाथनऑलिवर

1
मैं भी आश्चर्य है कि क्यों इस पुस्तकालय कार्यान्वयन में वे उपयोग करने के लिए चुना है int*के लिए std::arrayनहीं बल्कि के लिए std::vector
फ्रांस्वा एंड्रीक्स

1
दोनों के लिए इटरेटर प्रकार std::arrayऔर std::vectorअनिर्दिष्ट कर रहे हैं, जिसका अर्थ है कार्यान्वयन उन्हें कच्चे संकेत के रूप में परिभाषित करने के लिए अनुमति दी है (कोड संकलन नहीं होगा) या वर्ग प्रकार रैपर (कोड को केवल तभी वर्ग प्रकार है संकलित कर देगा stdएक ADL जुड़े नाम स्थान के रूप में)।
aschepler

1
यहां एक डेमो है जहां ADL एक उपनाम के साथ विफल रहता है, और यहां एक डेमो है जहां ADL एक नेस्टेड वर्ग के साथ सफल होता है। यहाँ और मेरे पहले के परीक्षणों में, std::vector<T>::iteratorएक उपनाम है।
user2357112
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.