或许以其他方式使用提升?
我想创建一个函数,从索引iStart中获取deque d
的子集到索引0,转换为新的deque,同时在d
中设置这些值到了0.我想到了这个:
std::deque<int> CreateSubset(std::deque<int>& d, int iStart )
{
int iSubsetSize = iStart+1;
std::deque<int> subset(iSubsetSize); // initialise a deque of a certain size.
std::deque<int>::iterator it = d.begin();
subset.assign (it, d.begin()+iStart+1);
for(;it != d.begin()+iStart+2; it++)
{
*it = 0;
}
return subset;
}
但这对我来说太可怕了 - 有更好的方式吗?
答案 0 :(得分:7)
以下是我在C ++ 11中的表现。我相信代码相当优雅,我认为没有什么特别低效的东西:
#include <iostream>
#include <deque>
#include <iterator>
#include <algorithm>
template <typename ForwardIt>
std::deque<int> extract(ForwardIt from, ForwardIt to)
{
using std::make_move_iterator;
std::deque<int> d2(make_move_iterator(from),
make_move_iterator(to));
std::fill(from,to,0);
return d2;
}
extract()
函数模板采用两个前向迭代器,将它们之间的内容移动到新创建的双端队列并在原始中将其设置为0.
所写的模板有两个假设:
通过引入更多模板参数或函数参数,可以放宽这两个假设。
如您所见,我使用std::make_move_iterator
转换输入迭代器以移动迭代器,从而导致元素被移动(而不是复制)到目标。只要它们是int
,它就不会产生任何影响。
我使用std::fill
算法将原始元素设置为0。
这是你可以调用这个函数模板的方法:
int main()
{
/* Creating d. */
std::deque<int> d
{ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 };
/* Extracting the first three elements into a new deque. */
auto d2 = extract(begin(d),begin(d) + 3);
/* Printing the results. */
std::cout << "d:\n";
for (const auto &elem : d)
std::cout << elem << ',';
std::cout << "\n\nd2:\n";
for (const auto &elem : d2)
std::cout << elem << ',';
std::cout << std::endl;
return 0;
}
答案 1 :(得分:3)
由于Container概念要求容器类型定义iterator
和const_reference
,所以甚至可以让jogojapan的答案更通用,而不需要多个模板参数。
template <typename Container>
Container extract(typename Container::iterator from,
typename Container::iterator to,
typename Container::const_reference replacement)
{
using std::make_move_iterator, std::fill;
Container new_container(make_move_iterator(from),
make_move_iterator(to));
fill(from,to,replacement);
return new_container;
}
你可以去哪里
deque<int> d { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 };
auto d2 = extract<deque<int>>(begin(d),begin(d) + 3, 0);
缺点是模板参数推断不再适用了。
好处是你可以使用几乎所有STL容器的代码,例如vector,deque,list,forward_list,set,map ......因为它们至少都有一个forward_iterator作为它们的迭代器类型。 您还可以指定“默认”替换。
也可以使用指针而不是引用,以便您可以决定是否要擦除(传递nullptr)或用特定值替换元素(将有效指针传递给相应的对象)。