Concatenating C++ iterator ranges into a const vector member variable at construction time(在构造时将 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 向量成员变量中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:在构造时将 C++ 迭代器范围连接到 const 向量成员变量中


基础教程推荐
- 在 C++ 中计算滚动/移动平均值 2021-01-01
- 如何检查GTK+3.0中的小部件类型? 2022-11-30
- 常量变量在标题中不起作用 2021-01-01
- 我有静态或动态 boost 库吗? 2021-01-01
- 如何在 C++ 中初始化静态常量成员? 2022-01-01
- 静态库、静态链接动态库和动态链接动态库的 .lib 文件里面是什么? 2021-01-01
- 如何将 std::pair 的排序 std::list 转换为 std::map 2022-01-01
- 这个宏可以转换成函数吗? 2022-01-01
- 如何通过C程序打开命令提示符Cmd 2022-12-09
- C++结构和函数声明。为什么它不能编译? 2022-11-07