有幸福的人使用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
答案 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。
社区维基,因为我只是在重复约翰内斯所说的话。