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

查看:13
本文介绍了在构造时将 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 上的 const,以便在 X 的其他方法中将其视为常量.

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

2) 我希望尽可能避免不必要的副本.也就是说,一种解决方案是有一个静态方法,它构造一个非常量临时到范围 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天全站免登陆