[英]Range based for with pair<Iterator,Iterator>
I have a question with respect to the following answer: 我对以下答案有疑问:
https://stackoverflow.com/a/15828866/2160256 https://stackoverflow.com/a/15828866/2160256
As stated there, we cannot use range based for with BGL like this: 如上所述,我们不能像BGL这样使用基于范围的BGL:
for(auto e : boost::edges(g))
// do something with e
However, here it states, that we can overload the begin() and end() functions that are required to use range based for semantics. 但是, 这里指出,我们可以重载使用基于语义的范围所需的begin()和end()函数。 So I tried:
所以我尝试过:
template<class I>
I begin(std::pair<I,I>& p)
{ return p.first;}
template<class I>
I end(std::pair<I,I>& p)
{ return p.second;}
However, the compiler still complains: 但是,编译器仍抱怨:
error: no matching function for call to '
begin(std::pair<some_really_ugly_type,some_really_ugly_type>&)
'错误:没有用于调用'
begin(std::pair<some_really_ugly_type,some_really_ugly_type>&)
的匹配函数
What am I doing wrong? 我究竟做错了什么? Does the name lookup not work?
名称查找不起作用吗? Or is this not possible after all?
或者这毕竟不可能吗? I also found this answer , which works, but shouldtn't it be possible with the begin/end free function overlods as well?
我也找到了这个答案 , 这个答案是有效的,但是开头/结尾自由函数的过度也不应该是可能的吗? Regards, Marti
问候,马蒂
BTW: I find it really tiresome to write 顺便说一句:我觉得写作真的很烦人
typename Graph::edge_iterator ebegin, eend;
std::tie(ebegin,eend) = boost::edges(_graph);
std::for_each(ebegin,eend,[&](const edge_descriptor& e){/*do something with e*/;});
UPDATE: C++17 should now allow the following :-) 更新:C ++ 17现在应该允许以下内容:-)
auto [ebegin,eend] = boost::edges(_graph);
Iterator pairs are not ranges by design! 迭代器对不是设计范围! The idea was specifically rejected from the language and library specification.
该想法被语言和图书馆规范明确拒绝。 See eg
见例如
If you "find it tiresome" to write the tie()
workaround, just use 如果您“发现它很烦人”来编写
tie()
解决方法,请使用
for (auto& edge : make_iterator_range(boost::edges(_graph)))
/*do something with edge*/;
You could alias boost::make_iterator_range
something shorter, but my editor¹ suggests make_iterator_range
as completion when I type mir
. 你可以将
boost::make_iterator_range
别名更短,但是当我输入mir
时,我的编辑器¹建议make_iterator_range
为完成。 This is plenty speedy for me 这对我来说很快
¹ of course, that editor is Vim ¹当然,那个编辑是Vim
In a range-based for
loop, name lookup for non-member begin()
and end()
uses ADL only. 在基于范围的
for
循环中,非成员begin()
和end()
名称查找仅使用ADL。 It doesn't perform ordinary unqualified lookup. 它不执行普通的非限定查找。 §6.5.4 [stmt.ranged]/p1.3:
§6.5.4[stmt.ranged] /p1.3:
if
_RangeT
is a class type, the unqualified-id sbegin
andend
are looked up in the scope of class_RangeT
as if by class member access lookup (3.4.5), and if either (or both) finds at least one declaration, [...]如果
_RangeT
是一个类类型,则在类_RangeT
的范围内查找unqualified-id sbegin
和end
,就像通过类成员访问查找(3.4.5)一样,并且如果其中任何一个(或两者)找到至少一个声明, [...]otherwise, begin-expr and end-expr are
begin(__range)
andend(__range)
, respectively, wherebegin
andend
are looked up in the associated namespaces (3.4.2).否则, begin-expr和end-expr分别是
begin(__range)
和end(__range)
,其中begin
和end
在相关的命名空间中查找(3.4.2)。 [ Note : Ordinary unqualified lookup (3.4.1) is not performed.[ 注意 :不执行普通的非限定查找(3.4.1)。 — end note ]
- 结束说明 ]
Hence, your begin()
and end()
overloads are not found. 因此,找不到您的
begin()
和end()
重载。
You cannot have free begin()
and end()
functions as per TC's answer . 根据TC的回答,您不能拥有免费的
begin()
和end()
函数。 However, what you can do, is just make your own class and add member begin
and end
to it: 但是,您可以做的只是创建自己的类并添加成员的
begin
和end
:
template <typename I>
struct iter_pair : std::pair<I, I>
{
using std::pair<I, I>::pair;
I begin() { return this->first; }
I end() { return this->second; }
};
And just use that instead of a normal pair
: 而只是使用它而不是正常的
pair
:
std::vector<int> v = {1, 2, 3, 4, 5};
iter_pair<decltype(v.begin())> pr{v.begin(), v.end()};
for (int i : pr) {
std::cout << i << ' ';
}
std::cout << std::endl;
I would expand on Barry's answer and suggest (until C++17) to add 我将扩展Barry的答案并建议(直到C ++ 17)添加
template <typename I>
iter_pair<I> make_range(std::pair<I, I> p) {
return iter_pair<I>(p);
}
to be used as 用作
for (auto e : make_range(boost::edges(g)))
// do something with e
Since the Boost FOREACH macro uses C++03 declarations and explicit template code, it ought to work with conventional lookup rules instead of special for
rules. 由于Boost FOREACH宏使用C ++ 03声明和显式模板代码,因此它应该使用传统的查找规则而不是特殊
for
规则。
You might make sure that it expands the old way even though range-based for
is available. 其膨胀,即使范围为基础的旧的方式也可以确保
for
可用。
Another approach would be to make your own class that is derived from the pair, but contains the begin
and end
members. 另一种方法是创建自己的类,该类派生自该对,但包含
begin
和end
成员。 Then write 然后写
for (e: mypair(p))
Instead of 代替
for (e: p)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.