如何实现自定义范围内的for循环?

时间:2018-12-28 21:19:59

标签: c++ c++11 ranged-loops

我真的很喜欢C ++ 11及更高版本支持的基于范围的循环。我希望出于某种理解的原因对其进行仿真。这是一个示例:

// 1
//#define ranged_for(X, T) \
//  for (std::vector<int>::iterator beg{ T.begin() },\
//      end{ T.end() }; beg != end; X = *beg, ++beg)\

// 2
//#define ranged_for(X, T) \
//  for (std::vector<int>::iterator beg{ T.begin() },\
//      end{ T.end() }; beg != end; ++beg, X = *beg)\

// 3
#define ranged_for(X, T) \
    for (std::vector<int>::iterator beg{ T.begin() },\
        end{ T.end() }; beg != end; ++beg)\
            X = *beg, 



int main(){
    std::vector<int> data{75, 435, 6578, 92, 123};

    auto i{ 0 };
    ranged_for(i, data)
        std::cout << i << std::endl;

    std::cout << std::endl;
    std::cin.get();
    return 0;
}

正如您在上方看到的那样,第一个宏不会获取第一个元素75,而是值0,而最后一个则不存在。这是因为我想在我的主文件中先打印x,然后再在循环的后迭代部分中分配它。

  • 第二个宏使程序崩溃,这是因为我认为取消引用了最后一个节点(哨兵节点)。

  • 第三个很好用,但是正如您所看到的,在宏扩展之后,我会得到:

    i = *beg, std::cout << i << std::endl;
    

这是因为上面的行被视为单个语句。有没有更好的方法和解释。谢谢大家好家伙!。

2 个答案:

答案 0 :(得分:1)

为什么您这么反对基于范围的C ++循环?

int i;
ranged_for(i, data)
    // ...

vs。

for(int i : data)

到目前为止,您需要预先声明i。您不能以这种方式使用引用!现在,让我们想象一下如何设法使其更加聪明:

ranged_for(int& i, data)

vs。

for(int& i : data)

您获得了什么?使用逗号而不是冒号???老实说,这不值得付出努力。需要考虑的场景:

auto i = data.end();
for(auto j = data.begin(); j != data.end(); ++j)
{
    if(someCondition)
        i = j;
}
if(i != data.end())
{
    // ...
}

好的,这已经非常罕见了。在很多情况下(如果不是大多数情况下),您可以将外部if的主体移动到内部,在末尾添加一条break指令。而且在这几种情况下,您仍然不能这样做-好吧,然后我会经历明确的迭代器循环-编写 并不繁琐...

答案 1 :(得分:1)

这对单行和多行示波器均适用:

#define ranged_for(X, T) \
    for(auto it=std::begin(T); it!=std::end(T) && (X=*it,true); ++it)

或者可以用来自动推断类型X的版本应该是,但是它需要一个附加的宏:

#define ranged_for(X, T) \
    {decltype(T)::value_type X; for(auto it=std::begin(T); it!=std::end(T) && (X=*it,true); ++it) {

#define range_end }}

int main(){
    std::vector<int> data{75, 435, 6578, 92, 123};

    ranged_for(i, data)
        std::cout << i << std::endl;
    range_end
}