C ++ 11:第二个元素的范围循环矢量? [英] C++11: Range-looping vector from the second element?

查看:180
本文介绍了C ++ 11:第二个元素的范围循环矢量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 std :: vector< std :: string> v; (初始化)。如何使用range-for循环访问除第一个元素之外的所有元素(在索引零处)。对于所有元素:
$ b $ pre $ for(const string& s:v)
process(s);

而不是 v a 可以使用范围表达式如何可以写范围表达式来跳过第一个元素(或者跳过前n个元素)

我知道如何使用 v.begin()+ 1 并使用经典循环来获得效果。我正在寻找新的,更具可读性,推荐的替代方案。可能类似于Python切片的东西? ...例如:

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $


解决方案

创建一个封装,begin()和end迭代器,然后你可以使用它作为第二个参数。

  #include< iostream> 
#include< vector>

模板< typename Collection>
class FromNth
{
Collection& coll_;
size_t offset_;

public:
FromNth(Collection& coll,size_t offset)
:coll_(coll),offset_(offset)
{
}

//很好的解析为const_iterator,如果需要的话
auto begin()const - > decltype(coll_.begin())
{return coll_.begin()+ offset_; }

auto end()const - > decltype(coll_.end())
{return coll_.end(); }
};

模板< typename Collection>
FromNth< Collection> makeFromNth(Collection& collection,size_t offset)
{
return FromNth< Collection>(collection,offset);
}

模板< typename Collection>
auto begin(const FromNth< Collection>&wrapper) - > decltype(wrapper.begin())
{
return wrapper.begin();
}

模板< typename Collection>
auto end(const FromNth< Collection>&wrapper) - > decltype(wrapper.end())
{
return wrapper.end();
}

int main()
{
std :: vector< int> (2),(3),(5),(7),(11),13,17,19,23 (auto x:makeFromNth(coll,1))


{
std :: cout<< x<< \\\
;
}
return 0;





$ b注意我的fromNthbegin是未定义的行为,如果输入的大小小于偏移量。 (如果它是相等的,那么它是很好的定义,并开始==结束)。请注意:如果您使用的是最新版本的boost,那么 iterator_range 可能会已经为您提供了一个类似于我的FromNth的收藏。 (auto const& s:boost :: make_iterator_range(v.begin()+ 1,v.end())

 
{
process(s);

$ / code>

注意:上面的代码在 decltype语句(在C ++ 11中需要模板)。
$ b

输出:

  sh-4.3 $ g ++ -std = c ++ 11 -o main * .cpp 
sh-4.3 $ main
3
5
7
11
13
17
19
23


I have a std::vector<std::string> v; (initialized). How can I use the range-for loop for accessing all elements except the first one (on index zero). For all elements:

for (const string & s: v)
    process(s);

Instead of the v a range expression can be used. How can I write the range expression to skip the first element (or skip the first n elements)?

I know how to get the effect using v.begin() + 1 and using the classic loop. I am searching for the new, more readable, recommended alternative to do that. Possibly something similar to Python slicing? ...like:

for s in v[1:]:
    process(s)

解决方案

Create a wrapper for which begin() and end() return the correct iterators and then you can use that as the second argument.

#include <iostream>
#include <vector>

template< typename Collection >
class FromNth
{
    Collection& coll_;
    size_t offset_;

public:
    FromNth( Collection& coll, size_t offset )
        : coll_( coll ), offset_( offset )
    {
    }

    // will nicely resolve to const_iterator if necessary
    auto begin() const -> decltype( coll_.begin() ) 
       { return coll_.begin() + offset_; }

    auto end() const -> decltype( coll_.end() )
       { return coll_.end(); }
};

template< typename Collection >
FromNth<Collection> makeFromNth( Collection& collection, size_t offset )
{
     return FromNth<Collection>( collection, offset );
}

template< typename Collection >
auto begin( const FromNth<Collection> & wrapper ) -> decltype( wrapper.begin() )
{   
   return wrapper.begin();
}

template< typename Collection >
auto end( const FromNth<Collection> & wrapper ) -> decltype( wrapper.end() )
{  
   return wrapper.end();
}

int main()
{
   std::vector< int > coll { 2, 3, 5, 7, 11, 13, 17, 19, 23 };

   for( auto x : makeFromNth( coll, 1 ) )
   {
       std::cout << x << '\n';
   }
   return 0;
}

Note that my fromNth "begin" is undefined behaviour if the size of the input is less than the offset. (If it's equal then it's well defined and begin == end). Therefore do a size check first.

Note: if you are using a recent enough version of boost then iterator_range may already provide you such a "collection" that is similar to my "FromNth".

for( auto const& s : boost::make_iterator_range( v.begin() + 1, v.end() ) )
{
    process( s );
}

Note: the code above worked on CodingGround using C++11 GNU 4.8.3. (That site is very slow though). From C++14 you will not need the ->decltype statements (which are needed in C++11 for templates).

Output:

sh-4.3$ g++ -std=c++11 -o main *.cpp
sh-4.3$ main
3
5
7
11
13
17
19
23 

这篇关于C ++ 11:第二个元素的范围循环矢量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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