Здравствуйте, _nn_, Вы писали:
Изменения:
Добавленны upto, downto, для генерации более малого кода.
Добавлен "#include <csstdef>" для std::ptrdiff_t. (Комо не съел без него.
)
Переписан с использованием макросов для генерации кода. (кому не нравится пропустить файл через препроцессор).
Добавленна возможность изменять переменную в цикле.
foreach(int& i, upto(10))
i = 11; // Цикл завершиться после этой строки
Если не хочется иметь возможность изменения, следует убрать mutable в range_iterator.
Может стоить сделать этот пункт опциональным ?
Замечания:
upto, downto не использовать если нет уверености в направлении.
Как обычно комментарии приветсвуются.
Код:
#ifndef NN_RANGE_H
#define NN_RANGE_H
#if defined(_MSC_VER)&& (_MSC_VER >= 1200)
#pragma once
#endif // _MSC_VER && (_MSC_VER >= 1200)
#include <cstddef>
#include <iterator>
namespace nn
{
// Type traits
template<typename T>
struct range_type_traits
{
static T begin()
{
return static_cast<T>(0);
}
static T step()
{
return static_cast<T>(1);
}
static bool up(const T& step)
{
return static_cast<T>(0)< step;
}
};
#define NN_RANGE_TRAITS(name, not_equal_expr, next_sign) \
template<typename T> \
struct name \
{ \
static bool not_equal(const T& left, const T& right, const T& step) \
{ \
/* Avoid unused variables */ \
left; \
right; \
step; \
return not_equal_expr; \
} \
static void next(T& first, const T& step) \
{ \
first next_sign step; \
} \
};
// UpTo
NN_RANGE_TRAITS(upto_container_traits, left < right, +=)
// DownTo
NN_RANGE_TRAITS(downto_container_traits, right < left, -=)
// Range
NN_RANGE_TRAITS(range_container_traits,
range_type_traits<T>::up(step) ? left < right : right < left,
+=)
// RRange
NN_RANGE_TRAITS(rrange_container_traits,
range_type_traits<T>::up(step) ? right < left : left < right,
-=)
#undef NN_RANGE_TRAITS
// Range Iterator
template<typename T, typename Traits>
class range_iterator
{
public:
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
typedef T value_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef range_iterator<T, Traits> this_type;
range_iterator(const T& first, const T& step = T()):
m_first(first),
m_step(step)
{
}
bool operator==(const this_type& right) const
{
return !(*this != right);
}
bool operator!=(const this_type& right) const
{
return Traits::not_equal(m_first, right.m_first, m_step);
}
this_type& operator++()
{
Traits::next(m_first, m_step);
return *this;
}
reference operator*() const
{
return m_first;
}
private:
mutable T m_first;
T m_step;
};
// Range Container
template<typename T, typename Traits>
class range_container
{
public:
typedef range_iterator<T, Traits> iterator;
typedef iterator const_iterator;
range_container(const T& first, const T& last, const T& step):
m_first(first, step),
m_last(last)
{
}
iterator begin() const
{
return m_first;
}
iterator end() const
{
return m_last;
}
private:
iterator m_first;
iterator m_last;
};
#define NN_RANGE(name, traits) \
template<typename T> \
range_container<T, traits<T> > name(const T& first, const T& last, const T& step) \
{ \
return range_container<T, traits<T> >(first, last, step); \
} \
template<typename T>\
range_container<T, traits<T> > name(const T& first, const T& last) \
{ \
return name(first, last, range_type_traits<T>::step()); \
} \
template<typename T>\
range_container<T, traits<T> > name(const T& last) \
{ \
return name(range_type_traits<T>::begin(), last); \
}
// UpTo
NN_RANGE(upto, upto_container_traits)
// DownTo
NN_RANGE(downto, downto_container_traits)
// Range
NN_RANGE(range, range_container_traits)
// RRange
NN_RANGE(rrange, rrange_container_traits)
#undef NN_RANGE
}// namespace nn
#endif // NN_RANGE_H