Re: [C++] range v4
От: _nn_ www.nemerleweb.com
Дата: 24.12.05 15:25
Оценка:
Здравствуйте, _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
  • http://rsdn.nemerleweb.com
    http://nemerleweb.com
     
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.