在构建时将C ++迭代器范围连接到const向量成员变量中 [英] Concatenating C++ iterator ranges into a const vector member variable at construction time

查看:177
本文介绍了在构建时将C ++迭代器范围连接到const向量成员变量中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类X,我在这里提供一个片段:

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

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

  private:
    vector<Y> const mVec;
};

现在我想为这个类添加一个新的连接构造函数,例如:

I now want to add a new concatenating constructor to this class, something like:

template <typename Iter1, typename Iter2>
X(Iter1 begin1, Iter1 end1, Iter2 begin2, Iter2 end2) : mVec(???) { ??? }

这样的构造函数将连接两个范围[begin1,end1)和[begin2,end2) mVec。挑战是

Such a constructor would catenate the two ranges [begin1, end1) and [begin2, end2) into mVec. The challenges are

1)我想保留在mVec的常量,所以它被认为是X的其他方法的常量。

1) I would like to preserve the const on mVec, so that it is considered constant throughout the other methods of X.

2)如果可能,我想避免不必要的副本。也就是说,一个解决方案是有一个静态方法,构造一个非const临时到范围1,插入范围2并返回它,然后定义连接构造函数

2) I would like to avoid unnecessary copies if at all possible. That is, one solution is to have a static method that constructs a non-const temporary to range 1, inserts range 2 and returns it, and then define the concatenating constructor to

template <typename Iter1, typename Iter2>
X(Iter1 begin1, Iter1 end1, Iter2 begin2, Iter2 end2) 
  : mVec(concatenate(begin1, end1, begin2, end2)) { }

但我相信这会复制所有的值至少一次额外的时间。

but that copies all the values at least one extra time, I believe.

推荐答案

很好的问题。我将尝试实现一个特定的迭代器封装类型,将两个范围转换为一个范围。

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 <typename T1, typename T2>
struct concat_iterator
{
public:
   typedef std::forward_iterator_tag iterator_category;
   typedef typename iterator_traits<T1>::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 <typename T1, typename T2>
concat_iterator<T1,T2> concat_begin( T1 b1, T1 e1, T2 b2, T2 e2 )
{
   return concat_iterator<T1,T2>(b1,e1,b2,e2);
}
template <typename T1, typename T2>
concat_iterator<T1,T2> concat_end( T1 b1, T1 e1, T2 b2, T2 e2 )
{
   return concat_iterator<T1,T2>(e1,e1,e2,e2);
}

现在您可以使用:

 class X {
 public:
    template <typename Iter, typename Iter2>
    X(Iter b1, Iter e1, Iter2 b2, Iter2 e2 ) 
      : mVec( concat_begin(b1,e1,b2,e2), concat_end(b1,e1,b2,e2) ) 
    {}

  private:
    vector<Y> 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.

这篇关于在构建时将C ++迭代器范围连接到const向量成员变量中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆