2012-03-08 7 views
11

सवाल की तरह, मैं इसके कारण के बारे में सोच रहा हूं। क्योंकि जब मैं const और गैर-const इटरेटर्स के बीच की दूरी प्राप्त करने का प्रयास करता हूं तो मुझे एक त्रुटि मिलती है।क्यों std :: दूरी कॉन्स और nonconst iterators के मिश्रण पर काम नहीं करता है?

vector<int> v; 
auto it=v.begin(); 
auto cit=v.cbegin(); 
distance(it,cit); 


no matching function for call to ‘distance(__gnu_cxx::__normal_iterator<int*, std::vector<int> >&, __gnu_cxx::__normal_iterator<const int*, std::vector<int> >&) 

इटरेटर की सीमित समझ से, मुझे कोई कारण नहीं दिखता कि इसे क्यों काम नहीं करना चाहिए।

उत्तर

19

आपके पास std::distance पर कॉल में एक परिवर्तनीय पुनरावर्तक और निरंतर पुनरावर्तक है, इसलिए टेम्पलेट तर्क कटौती विफल हो रही है। आप टेम्पलेट तर्क को स्पष्ट रूप से निर्दिष्ट करके इसे ठीक कर सकते हैं।

std::vector<int> v; 
auto i1 = v.begin(); 
auto i2 = v.cbegin(); 

auto dist = std::distance<std::vector<int>::const_iterator>(i1, i2); 
6

ऐसा इसलिए है क्योंकि std::distance() केवल एक टेम्पलेट पैरामीटर ले जाता है:

template <class InputIterator> 
iterator_traits<InputIterator>::difference_type 
distance(InputIterator first, InputIterator last); 

इसलिए, first और last एक ही प्रकार के लिए परिवर्तनीय होना चाहिए, और टेम्पलेट संकल्प दुर्भाग्य पर विचार नहीं करेंगे कि vector<int>::iteratorvector<int>::const_iterator के लिए परिवर्तनीय है।

+0

हम्म क्यों वे सिर्फ 2 टेम्पलेट पैरा के साथ टेम्पलेट नहीं बनाते हैं? क्या सीपीपी कोर लैंग में ऐसा करना संभव है? मैं क्या पूछ रहा हूं कि एक डिजाइन निर्णय या लैंग सीमा? – NoSenseEtAl

+0

स्पष्ट होने के लिए, मुझे पता है कि वे टेम्पलेट को 2 टेम्पलेट पैराम के साथ बना सकते हैं, लेकिन मुझे आश्चर्य है कि यह 1 टेम्पलेट पैराम संस्करण – NoSenseEtAl

+0

@NoSenseEtAl के साथ संघर्ष करेगा, मैं डिज़ाइन निर्णय कहूंगा। यह उस तरह से आसान है, और विभिन्न प्रकार के इटरेटर के बीच की दूरी की गणना (कहें, एक यादृच्छिक अभिगम इटरेटर और एक आगे इटरेटर) शायद ऐसा कुछ नहीं है जिसे आप अक्सर करना चाहते हैं। आप वास्तव में दो टेम्पलेट तर्कों के साथ एक संस्करण लिख सकते हैं, लेकिन वास्तविक दुनिया की समस्या क्या हल करेगी? –

3

std::distance उन दो iterators क्या काम नहीं कर रहा के साथ काम करेंगे टेम्पलेट तर्क अनुमान है। संकलक पहले टेम्पलेट तर्क के लिए किस प्रकार के विकल्प को हल करने का प्रयास कर रहा है और इसमें दो संभावित उम्मीदवार हैं, जो मानक विफलता के अनुसार विफल होते हैं।

आप दो चीजों में से एक कर सकते हैं, या तो एक ही प्रकार के केवल iterators तुलना करें या टेम्पलेट के प्रकार प्रदान:

std::distance<std::vector<int>::const_iterator>(v.begin(), v.cbegin()); 
4

हर किसी को कहते हैं, क्योंकि std::distance केवल एक इटरेटर प्रकार लेता है यह है, और टेम्पलेट तर्क कटौती यह चुनने में सक्षम नहीं है कि यह कौन सा होना चाहिए (भले ही उनमें से केवल एक संभव है, iteratorconst_iterator में परिवर्तित हो गया है लेकिन वापस नहीं)।

यह इस तरह एक टेम्पलेट कुछ लिख लायक हो सकता है:

template <typename Container> 
typename Container::const_iterator constify(const Container &, typename Container::iterator it) { 
    return it; 
} 

तो फिर तुम इस तरह टेम्पलेट कटौती के लिए मजबूर कर सकते हैं:

std::distance(constify(v, it), cit); 
बजाय कि महान लंबे प्रकार बाहर लिखने के

Container& पैरामीटर एक शर्म की बात है, यह वहां है क्योंकि AFAIK Container अकेले एक पुनरावर्तक तर्क से नहीं लिया जा सकता है।

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