#include #include #include #include template class concat_view { public: using value_type = T; using const_pointer = const value_type*; using const_reference = const value_type&; concat_view(std::initializer_list> spans) : spans_(spans) {} class iterator { public: using value_type = T; using difference_type = std::ptrdiff_t; using pointer = const T*; using reference = const T&; using iterator_category = std::input_iterator_tag; iterator(std::vector> const& spans, size_t outer, size_t inner) : spans_(spans), outer_(outer), inner_(inner) { advance_past_empty_spans(); } reference operator*() const { return spans_[outer_][inner_]; } iterator& operator++() { ++inner_; advance_past_empty_spans(); return *this; } bool operator==(const iterator& other) const { return outer_ == other.outer_ && inner_ == other.inner_; } bool operator!=(const iterator& other) const { return !(*this == other); } private: std::vector> spans_; size_t outer_ = 0; size_t inner_ = 0; void advance_past_empty_spans() { while (outer_ < spans_.size() && inner_ == spans_[outer_].size()) { ++outer_; inner_ = 0; } } }; iterator begin() const { return iterator(spans_, 0, 0); } iterator end() const { return iterator(spans_, spans_.size(), 0); } private: std::vector> spans_; };