2015-05-19 51 views
1

我想了解如何編寫一個採用const InputIterator的(獨立)函數,並在遍歷容器中的每個元素時執行一些簡單的操作。爲了簡單起見,我正在考慮一個簡單的打印功能,它將打印範圍在[first..last)之間的所有元素,但不允許該功能修改容器中的元素。下面是我到目前爲止有:如何使用const InputIterators爲泛型容器編寫函數?

#include<iostream> 
#include<vector> 
#include<list> 

using namespace std; 

template<class InputIterator> 
void print(const InputIterator& first, const InputIterator& last) 
{ 
    while (first != last) { 
    cout << *first << " "; 
    ++first; 
    } 
    cout << endl; 
} 


int main() 
{ 
    vector<int> v; 
    v.push_back(1); 
    v.push_back(3); 
    v.push_back(5); 
    v.push_back(7); 

    list<float> l; 
    l.push_back(11.1); 
    l.push_back(33.3); 
    l.push_back(55.7); 
    l.push_back(77.7); 

    print(v.cbegin(), v.cend()); 
    print(l.cbegin(), l.cend());  
} 

當我嘗試編譯代碼(使用C++ 11標誌gcc4.7),我收到以下錯誤:

iterator.cpp: In instantiation of 'void print(const InputIterator&, const InputIterator&) [with InputIterator = __gnu_cxx::__normal_iterator<const int*, std::vector<int> >]': 
iterator.cpp:32:29: required from here 
iterator.cpp:12:5: error: passing 'const __gnu_cxx::__normal_iterator<const int*, std::vector<int> >' as 'this' argument of '__gnu_cxx::__normal_iterator<_Iterator, _Container>& __gnu_cxx::__normal_iterator<_Iterator, _Container>::operator++() [with _Iterator = const int*; _Container = std::vector<int>; __gnu_cxx::__normal_iterator<_Iterator, _Container> = __gnu_cxx::__normal_iterator<const int*, std::vector<int> >]' discards qualifiers [-fpermissive] 
iterator.cpp: In instantiation of 'void print(const InputIterator&, const InputIterator&) [with InputIterator = std::_List_const_iterator<float>]': 
iterator.cpp:33:29: required from here 
iterator.cpp:12:5: error: passing 'const std::_List_const_iterator<float>' as 'this' argument of 'std::_List_const_iterator<_Tp>::_Self& std::_List_const_iterator<_Tp>::operator++() [with _Tp = float; std::_List_const_iterator<_Tp>::_Self = std::_List_const_iterator<float>]' discards qualifiers [-fpermissive] 

我我注意到,如果我刪除const要求,則代碼工作正常,分別將cbegincend分別替換爲beginend。有人能指出我在這裏錯過了什麼嗎?

+0

第一個被聲明爲const,但是你試圖修改它:'++ first;' – Borgleader

+1

你想要的是一個'const_iterator'而不是'const iterator' – NathanOliver

+4

按值傳遞迭代器。 – 0x499602D2

回答

3

您需要通過價值通過您的迭代器

template <class InputIterator> 
void print(InputIterator first, InputIterator last) 
{ 
    // as before 
} 

print不會修改任何內容的合同是隱含的你從來沒有分配給*first

需要修改的迭代器本身(實際做任何迭代),這是你不能把他們的const&(否則,第一件事情你必須再次複製它們) - 但修改迭代器與修改底層內容不一樣。

+0

我認爲契約是由'InputIterator'命名的,它是一個從*讀取的迭代器,而不是*寫入*的迭代器,它存在'OutputIterator'。 – Nawaz

+0

@Nawaz這不是一個真正的合同 - 它只是一個命名約定。如果我們有概念,並且可以執行'template ',那麼是的。 – Barry

+0

@Nawaz名字根本無關緊要 - 它只是模板類型的佔位符。你可以用T替換它,答案仍然有效。我之前也不知道:P – TCSGrad

0

混淆似乎源於混合迭代器和迭代器指向的數據。

  • 迭代器可以進行變異,同時保持尖括式爲只讀。

讓我們這些概念映射到原始指針:

int buffer[ARRAY_SIZE]; 

const int *ptr2c = &(buffer[0]); 

比。

int * const cptr = &(buffer[0]); 

考慮使用這些指針之一來循環「緩衝區」的元素。使用'ptr2c'時,應該能夠遍歷數組;通過這個變量不可能修改數組元素。

另一方面,'cptr'是一個const-pointer-to-int,允許您修改數組中的指向元素。但是,cptr本身不能修改爲指向任何其他位置。

回到你的例子,'const InputIterator'使迭代器本身不可修改,這不是你想要的。這很粗糙,但是,你可以通過指針來看到迭代器。當然,這些概念之後迅速發生分歧。

相關問題