在C ++中实现Foreach,这是一个穷人的方法

时间:2010-12-02 20:35:29

标签: c++

有幸福的人使用boost和Qt。在我目前的“嵌入式”项目中,我必须使用自制的容器类。好的,足够的抱怨。

我试图像这样实现一个简单且独立的foreach:

#define ForEachString(S,C) TString S;\
        for ( int i=0; i<C.GetSize() && (!!(&(S=C[i]))); ++i  )

它遍历一个包含op []和GetSize()方法的字符串列表。 E.g:

TStringList tables;
ForEachString( table, tables )
{
  //do sth. with tab.
}

原因很简单,每个容器类型都需要自己的宏。 因此我的问题是:它是否可以独立容器并且仍然是自包含的(所有必需的东西宏定义中)?

此致 的Valentin

6 个答案:

答案 0 :(得分:6)

也许您可以在类型T上进行参数设置:

#define ForEach(T,S,C) T S;\ 
    for ( int i=0; i<C.GetSize() && (!!(&(S=C[i]))); ++i  ) 

TStringList tables; 
ForEach( TString, table, tables ) 
{ 
  //do sth. with tab. 
} 

答案 1 :(得分:4)

我会推荐这个

#define ForEachString(S,C) \
  if(bool _j_ = false) ; else
    for (int _i_ = 0; _i_ < C.GetSize() && !_j_; ++_i_, _j_ = !_j_)
      for(S = C[_i_]; !_j_; _j_ = true)

TStringList tables;
ForEachString(TString table, tables)
{
  //do sth. with table
}

需要使用_j_的奇怪操作才能在循环内打破break。最好使用_i__j_这样的名称,以免干扰用户的本地循环变量。

答案 2 :(得分:2)

你的宏很危险。考虑:

if (<condition>)
    ForEachString(table, tables)
    {
        // do something
    }

此外,S被放入封闭范围。所以你不能在同一个块中有两个ForEachString调用。

如果你有一个前沿的编译器,range-based for-loops是C ++ 0x

的一部分

同样,使用C ++ 0x,您可以将TString S;替换为decltype(C[0]) S;

或者,只需创建宏的类型部分:

#define ForEachString(T, S, C) T S; ...  

答案 3 :(得分:2)

Boost库有一个类似于foreach的宏的实现,叫做BOOST_FOREACH就是这样做的。它独立于容器,也可以处理原始数组和C风格的字符串。实现简直可怕(许多用于类型内省的疯狂模板机制),但最终结果是快速,精简,平均和广泛使用。您可以找到有关此here的更多信息。

希望这有帮助!

答案 4 :(得分:0)

#define MY_CONTAINER(a, b) a b; \
    typedef a::iterator b##_itr;
#define for_each(itr, a)  for(a##_itr itr = a.begin(); itr != a.end(); ++itr) 

MY_CONTAINER(vector<int>, vnVec);
vnVec.push_back(2);
vnVec.push_back(3);
vnVec.push_back(10);

for_each(itr, vnVec)
  cout << *itr << endl;

答案 5 :(得分:-1)

如果你要创建这个宏的目标是学习,我建议你阅读Eric Niebler关于如何实现foreach的解释,Johannes Schaub指出 - litb(this)。它详细介绍了在尝试解决此问题时遇到的所有陷阱。

如果你主要关心的是获得一个有效的foreach宏,那么该函数会被记录下来并由Eric Niebler以BOOST_FOREACH的形式提交给Boost。

社区维基,因为我只是在重复约翰内斯所说的话。