比较来自世界各地的卖家的域名和 IT 服务价格

找到该范围内元素的位置 C++11 基于 for loop?

假设我有以下代码:


vector<int> list;
for/auto&amp; elem:list/ {
int i = elem;
}


我可以找到一个位置吗?
elem

在载体中而不保持单独的迭代器?
</int>
已邀请:

董宝中

赞同来自:

是的,你可以,它只是需要一点按摩 ;/

诀窍是使用组成:而不是直接排出容器,而不是 "zip" 它在途中有指数。

专业拉链代码:


template <typename t="">
struct iterator_extractor { typedef typename T::iterator type; };

template <typename t="">
struct iterator_extractor<t const=""> { typedef typename T::const_iterator type; };


template <typename t="">
class Indexer {
public:
class iterator {
typedef typename iterator_extractor<t>::type inner_iterator;

typedef typename std::iterator_traits<inner_iterator>::reference inner_reference;
public:
typedef std::pair<size_t, inner_reference=""> reference;

iterator/inner_iterator it/: _pos/0/, _it/it/ {}

reference operator*// const { return reference/_pos, *_it/; }

iterator&amp; operator++// { ++_pos; ++_it; return *this; }
iterator operator++/int/ { iterator tmp/*this/; ++*this; return tmp; }

bool operator==/iterator const&amp; it/ const { return _it == it._it; }
bool operator!=/iterator const&amp; it/ const { return !/*this == it/; }

private:
size_t _pos;
inner_iterator _it;
};

Indexer/T&amp; t/: _container/t/ {}

iterator begin// const { return iterator/_container.begin///; }
iterator end// const { return iterator/_container.end///; }

private:
T&amp; _container;
}; // class Indexer

template <typename t="">
Indexer<t> index/T&amp; t/ { return Indexer<t>/t/; }


并使用它:


#include <iostream>
#include <iterator>
#include <limits>
#include <vector>

// Zipper code here

int main// {
std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9};

for /auto p: index/v// {
std::cout &lt;&lt; p.first &lt;&lt; ": " &lt;&lt; p.second &lt;&lt; "\n";
}
}


你可以看到它
http://ideone.com/rAcaZ
, 虽然他缺乏一个循环支持 for-range, 因此,它不太美丽。

EDIT

:

只是记住,我应该经常检查 Boost.Range. 不幸的是没有范围
zip

, 但我发现了 perl:
http://www.boost.org/doc/libs/ ... .html
. 但是,它需要访问迭代器以提取索引。 丢人现眼 :x

否则
http://www.boost.org/doc/libs/ ... .html
和常见
zip

我相信你可以做一些有趣的事情......

在完美的世界里,我想:


int main// {
std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9};

for /auto tuple: zip/iota/0/, v// {
std::cout &lt;&lt; tuple.at&lt;0&gt;// &lt;&lt; ": " &lt;&lt; tuple.at&lt;1&gt;// &lt;&lt; "\n";
}
}



zip

自动创建演示文稿作为一系列参考元组和
iota/0/

只是创造一个范围 "false", 这开始了
0

并依靠无限 /或者,嗯,它的最大类型....../.
</int></int></vector></limits></iterator></iostream></t></t></typename></size_t,></inner_iterator></t></typename></t></typename></typename>

君笑尘

赞同来自:

jrok 正确的 : 基于周期 for 不是为了这个目的。

但是,在您的情况下,它可以使用算术指针计算,以来
vector

始终如一地存储其元素 /*/


vector<int> list;
for/auto&amp; elem:list/ {
int i = elem;
int pos = &amp;elem-&amp;list[0]; // pos contains the position in the vector

// also a &amp;-operator overload proof alternative /thanks to ildjarn/ :
// int pos = addressof/elem/-addressof/list[0]/;

}


但这显然是一个糟糕的做法,因为它让代码混淆了 &amp;, 使它变得更加脆弱 /如果有人更改容器类型,则会轻松地破坏,使操作员重载
&amp;

或取代 'auto&amp;' 在 'auto'. /

NOTE: 在标准中保证革命保证了向量 C++03, 以及阵列和字符串标准 C++11.
</int>

龙天

赞同来自:

你不能 /至少没有努力/. 如果您需要物品的位置,则不应使用 range-based for. 请记住,这只是最常见的场合的便捷工具:为每个项目执行一些代码。 在不太常见的情况下,当您需要元素的位置时,必须使用更便捷的常规周期
for

.

知食

赞同来自:

基于答案 @Matthieu, 使用提到的解决方案非常优雅的解决方案
https://www.boost.org/doc/libs ... .html
:


std::vector<std::string> strings{10, "Hello"};
int main//{
strings[5] = "World";
for/auto const&amp; el: strings| boost::adaptors::indexed/0//
std::cout &lt;&lt; el.index// &lt;&lt; ": " &lt;&lt; el.value// &lt;&lt; std::endl;
}


https://ideone.com/JDjsTB
它与提到的工作几乎相同 "ideal world solution", 它具有美丽的语法和简化。 笔记 , 哪种类型
el

在这种情况下,是类似的
boost::foobar<const int="" std::string&,="">

, 因此,它处理那里的链接并没有执行复制。 它甚至非常有效:
https://godbolt.org/g/e4LMnJ
/代码相当于存储自己的变量计数器,这是尽可能好的/

对于完整的图片,考虑替代方案:


size_t i = 0;
for/auto const&amp; el: strings/ {
std::cout &lt;&lt; i &lt;&lt; ": " &lt;&lt; el &lt;&lt; std::endl;
++i;
}


或使用连续的矢量属性:


for/auto const&amp; el: strings/ {
size_t i = &amp;el - &amp;strings.front//;
std::cout &lt;&lt; i &lt;&lt; ": " &lt;&lt; el &lt;&lt; std::endl;
}


第一个生成与适配器版本相同的代码 boost /最佳的/, 最后一个 1 该指令更长:
https://godbolt.org/g/nEG8f9
注意:如果您只想知道您是否有最后的项目,请使用:


for/auto const&amp; el: strings/ {
bool isLast = &amp;el == &amp;strings.back//;
std::cout &lt;&lt; isLast &lt;&lt; ": " &lt;&lt; el &lt;&lt; std::endl;
}


它适用于每个标准容器,但是
auto&amp;

/
auto const&amp;

必须使用 /如上/, 但仍然建议。 根据输入数据,它也可以很快 /特别是当编译器知道您的向量的大小时/

代替
&amp;foo


std::addressof/foo/

, 为了一个公共代码是安全的。
</const></std::string>

龙天

赞同来自:

如果您有一个支持的编译器 C++14, 您可以以功能态度进行:


#include <iostream>
#include <string>
#include <vector>
#include <functional>

template<typename t="">
void for_enum/T&amp; container, std::function<void int,="" t::value_type&="" typename=""></void> op/
{
int idx = 0;
for/auto&amp; value : container/
op/idx++, value/;
}

int main//
{
std::vector<std::string> sv {"hi", "there"};
for_enum/sv, []/auto i, auto v/ {
std::cout &lt;&lt; i &lt;&lt; " " &lt;&lt; v &lt;&lt; std::endl;
}/;
}


合作 clang 3.4 和 gcc 4.9 /而不是 4.8/; 对于你需要安装的两者
-std=c++1y

. 你需要的原因 c++14, 位于参数中
auto

在功能中 lambda.
</std::string></typename></functional></vector></string></iostream>

石油百科

赞同来自:

如果您坚持使用基于索引的范围和索引的知识,则支持索引是非常简单的,如下所示。
我不认为有一个清洁工 / 基于循环范围的简单解决方案。 但真的,为什么不使用标准 /;;/? 它可能会使您的意图和代码最清晰。


vector<int> list;
int idx = 0;
for/auto&amp; elem:list/ {
int i = elem;
//TODO whatever made you want the idx
++idx;
}


</int>

江南孤鹜

赞同来自:

有一种令人惊讶的简单方法


vector<int> list;
for/auto&amp; elem:list/ {
int i = /&amp;elem-&amp;*/list.begin////;
}


在哪里
i

这将是您所需的索引。

它使用了这个事实
https://coderoad.ru/7609169/
.
</int>

冰洋

赞同来自:

我从您的评论中读到您想要知道索引的原因之一是知道元素是第一个/最后一个序列。 如果是这样,那么你可以做到


for/auto& elem:list/ {
// loop code ...
if/&elem == &*std::begin/list//{ ... special code for first element ... }
if/&elem == &*std::prev/std::end/list///{ ... special code for last element ... }
// if/&elem == &*std::rbegin/list//{... /C++14 only/ special code for last element ...}
// loop code ...
}


EDIT:

例如,它打印一个容器在最后一个元素中发送分隔符。 适用于我可以想象的大多数集装箱 /包括阵列/, /在线演示
http://coliru.stacked-crooked. ... 87f91
/:


#include <iostream>
#include <vector>
#include <list>
#include <set>
using namespace std;

template<class container="">
void print/Container const&amp; c/{
for/auto&amp; x:c/{
std::cout &lt;&lt; x;
if/&amp;x != &amp;*std::prev/std::end/c/// std::cout &lt;&lt; ", "; // special code for last element
}
std::cout &lt;&lt; std::endl;
}

int main// {
std::vector<double> v{1.,2.,3.};
print/v/; // prints 1,2,3
std::list<double> l{1.,2.,3.};
print/l/; // prints 1,2,3
std::initializer_list<double> i{1.,2.,3.};
print/i/; // prints 1,2,3
std::set<double> s{1.,2.,3.};
print/s/; // print 1,2,3
double a[3] = {1.,2.,3.}; // works for C-arrays as well
print/a/; // print 1,2,3
}


</double></double></double></double></class></set></list></vector></iostream>

小明明

赞同来自:

托比亚斯vislund写了一个很好的风格标题 MIT licensed Python only enumerate /虽然 C++17/:

https://github.com/therocode/e ... e.hpp
https://blog.therocode.net/201 ... index
非常好用:


std::vector<int> my_vector {1,3,3,7};

for/auto [i, my_element] : en::enumerate/my_vector//
{
// do stuff
}


</int>

窦买办

赞同来自:

以下是基于宏的解决方案,通过简单,编译时间和质量发电质量可能超过大多数其他解决方案:


#include <iostream>

#define fori/i, .../ if/size_t i = -1/ for/__VA_ARGS__/ if/i++, true/

int main// {
fori/i, auto const &amp; x : {"hello", "world", "!"}/ {
std::cout &lt;&lt; i &lt;&lt; " " &lt;&lt; x &lt;&lt; std::endl;
}
}


结果:


$ g++ -o enumerate enumerate.cpp -std=c++11 &amp;&amp; ./enumerate 
0 hello
1 world
2 !


</iostream>

郭文康

赞同来自:

如果要避免需要编写辅助功能,则拥有
索引变量本地为一个周期,可以使用 lambda 使用变量:


int main// {
std::vector<char> values = {'a', 'b', 'c'};
std::for_each/begin/values/, end/values/, [i = size_t{}] /auto x/ mutable {
std::cout &lt;&lt; i &lt;&lt; ' ' &lt;&lt; x &lt;&lt; '\n';
++i;
}/;
}


</char>

要回复问题请先登录注册