Concatenating C++ iterator ranges into a const vector member variable at construction time

后端 未结 5 1368
情歌与酒
情歌与酒 2020-12-19 06:42

I have a class X, which I provide a snippet of here:

class X {
  public:
    template 
    X(Iter begin, Iter end) : mVec(begin, end) {}         


        
5条回答
  •  北荒
    北荒 (楼主)
    2020-12-19 07:20

    Nice problem. I would try to implement a particular iterator wrapper type that turns the two ranges into a single range. Something in the lines of:

    // compacted syntax for brevity...
    template 
    struct concat_iterator
    {
    public:
       typedef std::forward_iterator_tag iterator_category;
       typedef typename iterator_traits::value_type value_type;
       typedef *value_type pointer; 
       typedef &value_type reference;
    
       concat_iterator( T1 b1, T1 e1, T2 b2, T2 e2 ) 
          : seq1( b1 ), seq1end( e1 ), seq2( b2 ), seq2end( e2 );
       iterator& operator++() {
          if ( seq1 != seq1end ) ++seq1;
          else ++seq2;
          return this;
       }
       reference operator*() {
          if ( seq1 != seq1end ) return *seq1;
          else return *seq2;
       }
       pointer operator->() {
          if ( seq1 != seq1end ) return &(*seq1);
          else return &(*seq2);
       }
       bool operator==( concat_iterator const & rhs ) {
          return seq1==rhs.seq1 && seq1end==rhs.seq2 
              && seq2==rhs.seq2 && seq2end==rhs.seq2end;
       }
       bool operator!=( contact_iterator const & rhs ) {
          return !(*this == rhs);
       }
    private:
       T1 seq1;
       T1 seq1end;
       T2 seq2;
       T2 seq2end;
    };
    
    template 
    concat_iterator concat_begin( T1 b1, T1 e1, T2 b2, T2 e2 )
    {
       return concat_iterator(b1,e1,b2,e2);
    }
    template 
    concat_iterator concat_end( T1 b1, T1 e1, T2 b2, T2 e2 )
    {
       return concat_iterator(e1,e1,e2,e2);
    }
    

    Now you could use:

     class X {
     public:
        template 
        X(Iter b1, Iter e1, Iter2 b2, Iter2 e2 ) 
          : mVec( concat_begin(b1,e1,b2,e2), concat_end(b1,e1,b2,e2) ) 
        {}
    
      private:
        vector const mVec;
    };
    

    or (I have just thought of it) you don't need to redeclare your constructor. Make your caller use the helper functions:

    X x( concat_begin(b1,e1,b2,e2), concat_end(b1,e1,b2,e2) );
    

    I have not checked the code, just typed it here off the top of my head. It could compile or it could not, it could work or not... but you can take this as a start point.

提交回复
热议问题