1. C++ / Говнокод #18090

    +146

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    71. 71
    72. 72
    73. 73
    74. 74
    75. 75
    76. 76
    77. 77
    78. 78
    79. 79
    80. 80
    81. 81
    82. 82
    83. 83
    84. 84
    85. 85
    86. 86
    87. 87
    88. 88
    89. 89
    90. 90
    91. 91
    92. 92
    93. 93
    94. 94
    95. 95
    96. 96
    #ifndef FILTER_H
    #define FILTER_H
    
    #include <cassert>
    #include <vector>
    #include <algorithm>
    
    template<typename T>
    class filter_container;
    namespace detail {
    	template<typename Iter, typename Pred>
    	class filter {
    	public:
    		filter(Iter begin, Iter end, Pred pred) :_begin(begin), _end(end), _pred(pred) { }
    		filter(const filter & f) : _begin(f._begin), _end(f._end), _pred(f._pred) { }
    		filter & operator = (const filter & f) {
    			if(this != &f) {
    				_begin = f._begin;
    				_end = f._end;
    				_pred = f._pred;
    			}
    			return *this;
    		}
    		~filter() { }
    
    		class const_iterator {
    		public:
    			typedef typename Iter::reference reference;
    			typedef typename Iter::pointer pointer;
    			const_iterator(Iter iter, const filter & cont) :_iter(iter), _cont(&cont) { advance_until_pred(); }
    			const_iterator(const const_iterator & i) :_iter(i._iter), _cont(i._cont) { }
    			const_iterator & operator = (const const_iterator & i) {
    				if(this != &i) {
    					_iter = i._iter;
    					_cont = i._cont
    				}
    				return *this;
    			}
    			~const_iterator() { }
    			const_iterator & operator++() { advance_until_pred(); return *this; }
    			const_iterator operator++(int) {
    				const_iterator ret = *this;
    				advance_until_pred();
    				return ret;
    			}
    			const reference operator*() const { return *_iter; }
    			const pointer operator->() const { return &*_iter; }
    			bool operator == (const const_iterator & i) const {
    				assert(_cont == i._cont);
    				return _iter == i._iter;
    			}
    			bool operator != (const const_iterator & i) const { return !(*this == i); }
    		protected:
    			Iter _iter;
    			const filter * _cont;
    		private:
    			void advance_until_pred() {
    				if(_iter != _cont->_end) {
    					std::advance(_iter, 1);
    				}
    				_iter = std::find_if(_iter, _cont->_end, _cont->_pred);
    			}
    		private:
    			const_iterator();
    		};
    
    		class iterator : public const_iterator {
    		public:
    			iterator(Iter iter, const filter & cont) :const_iterator(iter, cont) { }
    			iterator(const iterator & i) :const_iterator(i) { }
    			iterator & operator = (const iterator & i) { const_iterator::operator=(i); return *this; }
    			~iterator() { }
    			reference operator*() { return *_iter; }
    			pointer operator->() { return &*_iter;  }
    		private:
    			iterator();
    		};
    
    		iterator begin() { return iterator(_begin, *this); }
    		iterator end() { return iterator(_end, *this); }
    		const_iterator cbegin() const { return const_iterator(_begin, *this); }
    		const_iterator cend() const { return const_iterator(_end, *this); }
    	private:
    		Iter _begin, _end;
    		Pred _pred;
    	private:
    		filter();
    	}; 
    }
    
    template<typename Iter, typename Pred> 
    detail::filter<Iter, Pred> filter(Iter begin, Iter end, Pred pred) {
    	return detail::filter<Iter, Pred>(begin, end, pred);
    }
    
    #endif // FILTER_H

    Тривиальная крестовщина, ничего выдающегося. Внезапно подумалось, что подобный контейнер был бы довольно удобен.
    Мне просто любопытно, насколько быстро этот пост будет слит автоминусаторами :)

    Запостил: Xom94ok, 29 Апреля 2015

    Комментарии (14) RSS

    • И пары часов не прошло.
      Ну, или оно по расписанию.
      А слив комментариев в комплекте тоже есть?
      Ответить
      • Ты вот скажи как хомячок суслику: константный объект надо от неконстантного наследовать или наоборот?
        Ответить
        • Я думаю, что надо уехать далеко-далеко, где есть море, алкоголь и прекрасный пол, чтобы такие вопросы в голову не приходили :) А пока этого не произошло, полагаю, можно отнаследовать неконстантный итератор от константного, чтобы расширить поле константных операций неконстантными.
          Ответить
          • Это неправильное использование ооп.
            Liskov substitution principle тебе в ребро.

            Наследование правильно применимо для реализации в отношения ЯВЛЯЕТСЯ
            Ответить
            • > Liskov substitution principle тебе в ребро.
              А че не так то? Неконстантный оператор можно подставить вместо константного. Все операции, которые умел константный, на нём работать тоже будут. А то, что у него operator *() возвращает неконстантную ссылку - всем похуй, вместо константных они прокатят. Поэтому неконстантный итератор ЯВЛЯЕТСЯ частным случаем константного.
              Ответить
              • Плюсую за такое аргументированное объяснение моей ленивости писать два отдельных класса итераторов :)
                В бусте, оказывается, есть filter_iterator, но он без контейнера и, как мне кажется, тяжеловат - каждый инстанс хранит в себе предикат, исходный итератор и итератор на конец диапазона.
                Ответить
    • private:
          iterator();
      Нафиг?

      P.S. В общем-то копирование, присваивание и деструктор тоже можно не писать, компилятор сам справится.
      Ответить
      • И надо бы ещё несколько тайпдефов добавить - iterator_category, difference_type и value_type. Без них некоторые бустовские либы смотрят на итератор как на говно (std::iterator_traits ломается).
        Ответить
        • А итератор_категори что делает?
          Ответить
          • А это вид итератора. По нему некоторые алгоритмы могут оптимизироваться или ругаться, что им надо более крутой итератор.

            http://en.cppreference.com/w/cpp/iterator/iterator_tags
            Ответить
        • Можно ещё унаследоваться от std::iterator, он некоторые тайпдефы может сам добавить.
          Ответить
      • > копирование, присваивание и деструктор тоже можно не писать
        Иной раз надо добавить другой конструктор и вот думай потом "постираются" ли прочие конструктора или не надо их добавлять руками, ибо компилятор сам справится
        Ответить
      • > Нафиг?
        По привычке, чтобы самому не накосячить; аналогично с присваиванием, деструктором и копированием. Плюс там можно бряк поставить и отследить, когда они вызываются, что тоже иногда любопытно.
        Ответить
    • vanished
      Ответить

    Добавить комментарий