你对循环宏有什么看法?

时间:2013-05-10 22:39:16

标签: c++ for-loop c++11

#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)不适用于所有数据结构,例如列表。但我仍然觉得它很方便。

3 个答案:

答案 0 :(得分:3)

不确定我喜欢这个。 if条件没有相应的else子句,因此循环体内的else不会绑定到正确的ifif后面的else许多else条款不会导致错误。

您可以尝试使用then子句而不是if的{​​{1}}子句。 编辑:实际上,由于您只使用if来引入变量,为什么不像其他地方那样使用for

您的宏也会影响我称之为b的任何内容,这可能非常烦人。也许使用令牌粘贴来给出一个不太可能的名字?

答案 1 :(得分:2)

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

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

另请注意,在许多情况下,诸如copy(对流迭代器)和for_each(可能与lambdas一起)等算法可以非常明确地执行您可能尝试使用for做的事情循环,并支持所有迭代方向,只需选择传入算法的迭代器。

答案 2 :(得分:0)

建议相同/类似功能的包装器。我所知道的社区维基只是一个概念,需要改进。

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