python中的range函數表示一個連續的有序序列,range使用起來很方便,因為在定義時就隱含了初始化過程,因為只需要給begin()和end()或者僅僅一個end(),就能表示一個連續的序列。還可以指定序列產生的步長,如range(0,10,8)產生的序列為[0, 8], 默認的步長為1,range(3)表示的序列是[0,1,2]。range的遍歷也很方便:
for i in range(3):
print i
c++11中增加了一項新特性range-based for循環,其實這也不是什麼新東西,在c#、java和python等語言中已經有了。這種循環方式非常簡潔,它的內部其實是對傳統的begin()/end()方式的遍歷做了包裝,算是一個循環的語法糖。用法很簡單:
//遍歷vector
std::vector<int> v;
for(auto i : v)
{
cout<<i<<endl;
}
//以只讀方式遍歷map
std::map<string, int> map;
for(const auto& item : map)
{
cout << item->first<<item->second<<endl;
}
c++11的range-based for循環有意思的地方是他可以支持自定義類型的遍歷,但是要求自定義類型滿足三個條件:
滿足這三個條件之後,我們自定義的類型就能支持range-based for循環了。
再回到剛才提到的python的range(),它很好用,但是c++中目前還沒有類似的東西,雖然標准庫中有很多容器如vector、list、queue、map、初始化列表和array等等都已經支持了range-based for循環,但是他們使用起來還是不夠方便,比如要生成一個有序序列時,需要專門去初始化,如果有一個類似於python range的東西就比較完美了。雖然c++11現在沒有,但我們可以自己用c++11去實現一個類似的range,而且我還想讓這個range比python的range更強大,讓它不僅僅能支持整數還能支持浮點數,同時還能雙向迭代,實現這個range還是比較簡單的,看看具體實現吧:
namespace Cosmos
{
template<typename value_t>
class RangeImpl
{
class Iterator;
public:
RangeImpl(value_t begin, value_t end, value_t step = 1) :m_begin(begin), m_end(end), m_step(step)
{
if (step>0&&m_begin >= m_end)
throw std::logic_error("end must greater than begin.");
else if (step<0 && m_begin <= m_end)
throw std::logic_error("end must less than begin.");
m_step_end = (m_end - m_begin) / m_step;
if (m_begin + m_step_end*m_step != m_end)
{
m_step_end++;
}
}
Iterator begin()
{
return Iterator(0, *this);
}
Iterator end()
{
return Iterator(m_step_end, *this);
}
value_t operator[](int s)
{
return m_begin + s*m_step;
}
int size()
{
return m_step_end;
}
private:
value_t m_begin;
value_t m_end;
value_t m_step;
int m_step_end;
class Iterator
{
public:
Iterator(int start, RangeImpl& range) : m_current_step(start), m_range(range)
{
m_current_value = m_range.m_begin + m_current_step*m_range.m_step;
}
value_t operator*() { return m_current_value; }
const Iterator* operator++()
{
m_current_value += m_range.m_step;
m_current_step++;
return this;
}
bool operator==(const Iterator& other)
{
return m_current_step == other.m_current_step;
}
bool operator!=(const Iterator& other)
{
return m_current_step != other.m_current_step;
}
const Iterator* operator--()
{
m_current_value -= m_range.m_step;
m_current_step--;
return this;
}
private:
value_t m_current_value;
int m_current_step;
RangeImpl& m_range;
};
};
template<typename T, typename V>
auto Range(T begin, T end, V stepsize)->RangeImpl<decltype(begin + end + stepsize)>
{
return RangeImpl<decltype(begin + end + stepsize)>(begin, end, stepsize);
}
template<typename T>
RangeImpl<T> Range(T begin, T end)
{
return RangeImpl<T>(begin, end, 1);
}
template<typename T>
RangeImpl<T> Range(T end)
{
return RangeImpl<T>(T(), end, 1);
}
}
再看看測試代碼:
void TestRange()
{
cout << "Range(15):";
for (int i : Range(15)){
cout << " " << i;
}
cout << endl;
cout << "Range(2,6):";
for (int i : Range(2, 6)){
cout << " " << i;
}
cout << endl;
cout << "Range(10.5, 15.5):";
for (float i : Range(10.5, 15.5)){
cout << " " << i;
}
cout << endl;
cout << "Range(35,27,-1):";
for (int i : Range(35, 27, -1)){
cout << " " << i;
}
cout << endl;
cout << "Range(2,8,0.5):";
for (float i : Range(2, 8, 0.5)){
cout << " " << i;
}
cout << endl;
cout << "Range(8,7,-0.1):";
for (auto i : Range(8, 7, -0.1)){
cout << " " << i;
}
cout << endl;
cout << "Range('a', 'z'):";
for (auto i : Range('a', 'z'))
{
cout << " " << i;
}
cout << endl;
}
測試結果:

可以看到這個range不僅僅會根據步長生成有序序列,還能支持浮點類型和char類型以及雙向迭代,比python的range更強大。