C++ 基于范围的配对<;迭代器,迭代器>;

C++ 基于范围的配对<;迭代器,迭代器>;,c++,for-loop,boost,iterator,C++,For Loop,Boost,Iterator,我对以下答案有一个问题: 如前所述,我们不能将基于范围的用于BGL,如下所示: for(auto e : boost::edges(g)) // do something with e 但是,它指出,我们可以重载使用基于范围的语义所需的begin()和end()函数。所以我试着: template<class I> I begin(std::pair<I,I>& p) { return p.first;} temp

我对以下答案有一个问题:

如前所述,我们不能将基于范围的用于BGL,如下所示:

   for(auto e : boost::edges(g))
       // do something with e
但是,它指出,我们可以重载使用基于范围的语义所需的begin()和end()函数。所以我试着:

   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;}
更新:C++17现在应该允许以下操作:-)


在基于范围的
for
循环中,非成员
begin()
end()
的名称查找仅使用ADL。它不执行普通的非限定查找。§6.5.4[标准范围]/p1.3:

  • 如果
    \u range
    是类类型,则在类
    \u range
    的范围内查找不合格ID
    开始
    结束
    ,就像通过类成员访问一样 查找(3.4.5),如果其中一个(或两个)找到至少一个 宣言,[……]

  • 否则,begin expr和end expr是
    begin(\uu范围)
    end(_范围)
    ,其中
    begin
    end
    分别在 相关名称空间(3.4.2)。[注:普通不合格查询 (3.4.1)未执行。-结束注释]


因此,找不到您的
begin()
end()
重载。

由于Boost FOREACH宏使用C++03声明和显式模板代码,因此它应该使用常规的查找规则,而不是针对
规则的特殊

即使基于范围的
for
可用,您也可以确保它以旧的方式展开

另一种方法是创建您自己的类,该类派生自该对,但包含
begin
end
成员。然后写

for (e: mypair(p))
而不是

for (e: p)

根据,您不能使用免费的
begin()
end()
函数。但是,您可以做的只是创建自己的类,并向其中添加成员
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; }
};

迭代器对是而不是设计范围!语言和库规范明确拒绝了这个想法。见例

如果您觉得编写
tie()
变通方法“令人厌烦”,只需使用

for (auto& edge : make_iterator_range(boost::edges(_graph)))
    /*do something with edge*/;
您可以将
boost::make_iterator_range
的别名改短一些,但我的编辑器建议在我键入
mir
时将
make_iterator_range
作为补全。这对我来说太快了



当然,这个编辑器是Vim,我会在Barry的答案上进行扩展,并建议(在C++17之前)添加


做这件事之前要三思。有充分的理由不假设任何迭代器对都是一个范围。请参阅我对我最喜欢的成语的回答。@ SEHE的好理由建议添加类型<代码>范围< /代码>,但标准既不做,也不增加范围,也不允许迭代器的PAR用于范围循环。干得好谢谢,我对冗长的OneLiner没有任何问题,但这三个行程序确实有害处:-)我用boost替换了我自己的make_范围:)谢谢你的反馈。欢迎我建议使用helper函数的原因是允许它推断模板类型,而不是显式声明:
for(auto e:make_range(boost::edges(g))
而不是
for(auto e:iter_pair(boost::edges(g))
,在这里您必须猜测
的正确类型。C++17应该引入构造函数调用,减少对helper函数的需要。
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; }
};
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;
for (auto& edge : make_iterator_range(boost::edges(_graph)))
    /*do something with edge*/;
template <typename I>
iter_pair<I> make_range(std::pair<I, I> p) {
    return iter_pair<I>(p);
}
for (auto e : make_range(boost::edges(g)))
    // do something with e