你觉得这个for循环宏怎么样?

What do you think to this for loop macro?

本文关键字:循环 怎么样 for      更新时间:2023-10-16
#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)不适用于所有数据结构,如列表。但我还是觉得很方便。

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

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

你的宏也阴影任何我称之为b,这可能是非常烦人的。也许用标记粘贴给它一个不太可能的名字?

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

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

还要注意,在许多情况下,像copy(流迭代器)和for_each(可能与lambdas结合使用)这样的算法可以非常有表现力地完成您可能尝试使用for循环做的事情,并支持所有方向的迭代,只需选择传递给算法的迭代器。

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

#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;
    }
}