用于STL Iterables的迭代器循环的宏

时间:2011-12-09 01:12:12

标签: c++ generics stl macros iterator

概念

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

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<TYPE>。这可能吗?如果是这样,我该怎么做?

约定

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

胜利

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

6 个答案:

答案 0 :(得分:8)

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

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

答案 1 :(得分:2)

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

答案 2 :(得分:2)

如果您使用的是C ++ 11,则可以使用new语法。

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进行编译。

答案 3 :(得分:1)

如果您使用的是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);
}

答案 4 :(得分:0)

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

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

当然必须...... MACROS EVIL

如果您坚持使用古老的编译器,您可以随时使用

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

答案 5 :(得分:0)

我想扩展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完全相同。

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