【问题标题】:Macro for Iterator Loop for STL Iterables用于 STL 可迭代的迭代器循环的宏
【发布时间】:2011-12-09 01:12:11
【问题描述】:

概念

所以,我正在尝试定义一个宏来简化以下代码:

for (vector<TYPE>::iterator iter = iterable.begin(); 
             iter != iterable.end(); iter++)

for (map<TYPE, TYPE>::iterator iter = iterable.begin();
             iter != iterable.end(); iter++)

等等

现有工作

到目前为止,我有

#define every(iter, iterable) ::iterator iter = iterable.begin(); iter != iterable.end(); iter++
for (vector<TYPE> every(iter, iterable))

但我想进一步简化。

目标

理想情况下,我希望能够做到

for (every(iter, iterable))

这意味着我需要以某种方式获取可迭代对象的class&lt;TYPE&gt;。这可能吗?如果是这样,我该怎么做?

规定

  • 理想情况下,这需要进入已设置的(相对)大型代码库以访问 iterator 对象。
  • 我在 C++11 之前的编译器上运行

胜利

#define every(iter, iterable) typeof(iterable.begin()) iter = iterable.begin(); iter != iterable.end(); iter++
for (every(iter, iterable))

【问题讨论】:

  • 你能用C++11和decltype吗?如果没有,你可以写一个小的 trait 类。

标签: c++ generics stl macros iterator


【解决方案1】:

这个答案确实依赖于 C++11,但它需要typeof,而某些编译器可能没有。应该适用于任何最近的 g++

#define For(iter, iterable) for(typeof((iterable).begin()) iter = (iterable).begin(); iter != (iterable).end(); ++iter)

【讨论】:

  • 太简单了,我错过了!
  • 我不知道typeof 可以这样使用。 +1
  • 我认为typeof 有一些限制。如果f() 返回一个引用类型,例如int&amp;,那么(据我所知)typeof(f())int,而不是int&amp;。但它在我刚刚描述的宏中做得很好。
  • 不错的解决方案,尽管如果编译器支持,Ross 的for( auto&amp; x : v ) 会是我的首选(即您使用的是 C++11)。
  • 您现在也可以使用 auto 而不是 typeof 来实现此目的。
【解决方案2】:

如果你的编译器支持 C++0x,你可以使用for(auto iter = iterable.being(); iter != iterable.end(); iter++)

【讨论】:

  • 在 C++0x 中,可以使用 range-for 代替。 ++iter 在 C++ 中也是首选。 ;)
【解决方案3】:

如果你使用的是 C++11,你可以使用新的 for 语法。

vector<double> v(9, 0.5);
auto total = 0.;
for (auto x: v) {
    total += x;
}

如果您需要参考来修改值,您可以使用:

vector<double> v(9, 0.5);
for (auto &x: v) {
    x = 5;
}

只需使用标志 -std=c++0x 编译即可。

【讨论】:

    【解决方案4】:

    如果您使用的是 c++11,请使用 auto!

    for (auto it = vec.begin(); it != vec.end(); it++)
    {
    }
    

    编辑:

    这将是你的宏:

    #define every(iter, iterable) auto iter = iterable.begin(); iter != iterable.end(); iter++
    

    然后是实现:

    for(every(iter, iterable))
    {
        UseElement(*iter);
    }
    

    【讨论】:

    • auto 没有正确返回迭代器(或者至少,当我使用 auto 时,我收到错误消息,例如“类型中的 operator++ 不匹配”)
    • 是一样的。我的印象是auto 正在做一些不同的事情,因为我正在使用预 C++11 编译器进行编译
    • 啊,是的,它是 C++11 的一个特性,所以这部分很重要 :)
    • 在 C++11 中不需要这个宏。 (理想情况下,目前可能支持自动,但不支持范围。)
    【解决方案5】:

    为什么不简单地使用 std::for_each 呢?在 C++11 中,您可以将它们与 lambda 一起使用。

    C++11 also has a range base loop.

    template<typename T>
    void Foo(const T& x)
    {
        for (auto& i : x)
            std::cout << i << std::endl;
    }
    

    当然是必须的……宏是邪恶的

    如果你被一个古老的编译器卡住了,你总是可以这样做

    typedef std::map<int,int> IntMap_t;
    IntMap_t tmap;
    for( IntMap_t::iterator iter = tmap.begin();
             iter != tmap.end();
             ++iter)
    {
    }
    

    【讨论】:

    • 如果我可以假设iterable 将是map&lt;int, int&gt;,我不能将它包含在宏中吗?除非map&lt;int, int&gt; 在 C++ 中是某种奇怪的“通用可迭代”
    【解决方案6】:

    我想扩展 Aaron McDaid 的非常好的答案。我在 pre-C++0x 环境中找到了非常相似的解决方案(我将宏称为FOREACH)。它适用于普通iteratorreverse iterator。但是如何在const_iteratorconst_reverse_iterator 上完成呢?不幸的是,cbegin() 是 C++0x 功能,typeof(container)::const_iterator 不起作用。一个非常小的模板类可以解决这个问题。这是我的代码:

    template <class T>
    struct IterType { typedef typename T::const_iterator citer_t; };
    
    #define FOREACHCONST(_CIter, _Container) \
      for(IterType<typeof(_Container)>::citer_t _CIter = (_Container).begin(); \
          _CIter != (_Container).end(); ++_CIter )
    

    它的工作方式与FOREACH 完全相同。

    有趣的是,这在模板函数中不起作用。在这种情况下,必须在 IterType 之前添加 typename 关键字,但在这种情况下,它不能在模板函数之外使用。

    【讨论】:

      猜你喜欢
      • 2012-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-24
      相关资源
      最近更新 更多