3
#define for_all_impl(var, cont, mode) for (auto var##_begin_it = cont.##mode##begin(), var##_end_it = cont.##mode##end(), var##_it = var##_begin_it; var##_it != var##_end_it; ++var##_it) if (bool b = true) for (auto& var(*var##_it); b; b = false, var) if (bool b = true) for (const auto var##_num(var##_it - var##_begin_it); b; b = false, var##_num)
#define for_all(var, cont) for_all_impl(var, cont, )
#define for_all_const(var, cont) for_all_impl(var, cont, c)
#define for_all_reverse(var, cont) for_all_impl(var, cont, r)
#define for_all_const_reverse(var, cont) for_all_impl(var, cont, cr)

int main()
{
    std::vector<int> a; a.push_back(0); a.push_back(1); a.push_back(2); a.push_back(3);
    for_all(i, a)
    {
        std::cout << i_num << ": " << i << std::endl;
    }
}

我这样做的原因是因为长期以来 C++ 没有简单的快捷方式来遍历数据结构而无需大量输入。现在我们有了新的基于范围的 for 循环语法,但是没有简单的方法可以给你当前的索引或向后退(我知道)。

我花了很多时间设计它,所以请给它怀疑的好处,并指出任何大的缺陷。我假设只有常规变量名将用作参数。我不会为每个人提出它,但从现在开始我会在我的项目中使用它,除非它有很大的问题。

谢谢。

编辑:我意识到索引计数器(i_num)不适用于所有数据结构,例如列表。但我仍然认为它很方便。

4

3 回答 3

3

不确定我喜欢这个。if条件句没有对应的else子句,因此else循环体中的 s 不会绑定到正确if的,并且if后面的子句太多else也不会导致错误。

您可以尝试使用else子句而不是 the 的then子句if编辑:实际上,既然您只使用ifs 来引入变量,那么为什么不像for您在其他地方所做的那样使用呢?

你的宏也会影响我调用的任何东西b,这可能很烦人。也许使用令牌粘贴来给它一个不太可能的名字?

于 2013-05-10T22:55:19.430 回答
2

这是一个相当主观的问题,所以我的回答也可能是主观的。

通过使用这个宏,您实际上将创建一种 C++ 方言,其他通常精通 C++ 的人一开始都无法舒适地阅读。这对于您自己维护的项目来说不是问题,但在任何专业环境中,其他人将来必须阅读或更新您的代码是生活中的事实。您编写一次代码(这可能会节省少量编码),人们将在应用程序的整个生命周期内阅读它。由于这些原因,我建议不要使用宏。

另请注意,在许多情况下,copy(对于流迭代器)和for_each(可能与 lambdas 结合使用)之类的算法可以非常有表现力地执行您可能尝试使用 for 循环执行的操作,并支持所有方向的迭代,只需选择哪个传递给算法的迭代器。

于 2013-05-10T23:11:25.377 回答
0

建议相同/相似功能的包装器。据我所知,社区 wiki 这只是一个概念 atm,需要改进。

#include <iostream>
#include <vector>

template < typename Iter >
struct range
{
    Iter m_begin;
    Iter m_end;

    struct Iterator// : std::iterator < ... >
    {
        Iter m;

        Iter operator*() const
        { return m; }
        bool operator!= (Iterator const& p) const
        { return m != p.m; }
        Iterator& operator++()
        { ++m; return *this; }
    };

    Iterator begin()
    {
      return Iterator{m_begin};
    }
    Iterator end()
    {
      return Iterator{m_end};
    }
};

template < typename Cont >
range < typename Cont::iterator > make_range(Cont& p)
{ return {p.begin(), p.end()}; }

template < typename Cont >
range < typename Cont::reverse_iterator > make_reverse_range(Cont& p)
{ return {p.rbegin(), p.rend()}; }


int main()
{
    std::vector<int> v = {1,2,3,4,5};
    for(auto it : make_reverse_range(v))
    {
        auto var = *it;
        std::cout << var << std::endl;
    }
}
于 2013-05-11T01:01:40.367 回答