2012-03-08 83 views
11

像問題所述,我想知道原因。因爲當我嘗試獲取const與非const迭代器之間的距離時出現錯誤。爲什麼std :: distance對const和nonconst迭代器的混合不起作用?

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); 

因此,firstlast必須轉換爲同一類型和模板分辨率遺憾的是沒有考慮vector<int>::iterator可轉換爲vector<int>::const_iterator

+0

嗯爲什麼不他們只是用2模板參數創建模板?是否有可能在cpp core lang中執行?我所要求的是設計決定還是語言限制? – NoSenseEtAl 2012-03-08 18:17:59

+0

要清楚,我知道他們可以用2個模板參數製作模板,但是我想知道它會與1個模板參數版本 – NoSenseEtAl 2012-03-08 18:18:55

+0

@NoSenseEtAl發生衝突,我會說設計決定。這樣做更簡單,並且計算不同種類的迭代器(例如,一個隨機訪問迭代器和一個前向迭代器)之間的距離可能不是您想要經常執行的操作。你確實可以用兩個模板參數來編寫一個版本,但是解決什麼現實世界的問題呢? – 2012-03-08 18:23:10

3

std::distance將與這兩個迭代器什麼是不工作的工作是在模板參數推斷。編譯器試圖解決什麼類型替代第一個模板參數,並有兩個潛在的候選人,根據標準,最終失敗。

你可以做兩件事情之一,無論是隻比較同類型的迭代器,或提供類型的模板:由於大家都說

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

,這是因爲std::distance只需要一個迭代器類型,模板參數扣除無法選擇它應該是哪一個(即使iterator轉換爲const_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不能從一個迭代器參數推導出來。

相關問題