Qt'中foreach的实现
来源:互联网 发布:最新网络名词英文 编辑:程序博客网 时间:2024/04/27 21:49
foreach可以用来遍历容器,比如下面的使用场景:
QVector<int> container;container.push_back(1);container.push_back(2);container.push_back(3);foreach(int x, container){ qDebug() << x;}关于foreach的实现代码可以在QtCore的qglobal.h中查看。本篇博客介绍下它的大概实现,可以当作是对它的模拟仿真。
上面提到了它的应用场景,也就是它的使用方法。看下它的原型:
Q_FOREACH(variable, container)
variable表示容器中的每个元素,包括类型和变量。container表示容器对象。foreach本身就是一个宏定义,内容是对容器的遍历。遍历容器,可以使用for循环来做,比如:
for (int i = 0; i < container.size(); ++i){ int x = container[i]; qDebug() << x;}或者,可以使用迭代器来实现,比如:
typedef QVector<int> Container;for (Container::const_iterator iter = container.begin(); iter != container.end(); ++iter){ int x = *iter; qDebug() << x;}使用迭代器方式,应该如何实现?
foreach传入container参数,container的类型不确定,还需要取得迭代器,取迭代器的begin()和end(),首先面临的问题是如何取得容器类型,容器的迭代器。
类型提取,类型萃取,可以使用模板。比如:
template<typename Container>typename Container::iterator begin(const Container& c){ //typedef Container::iterator Iterator; return c.begin();}
可以取得模板类型的iter,begin,end,但是模板不能直接使用。可以考虑把这几个变量放在一个类中,比如:
template<typename Container>class DummyClass{public: DummyClass(const Container& c) : _c(c), _b(c.begin()), _e(c.end()){} const Container& _c; typename Container::iterator _b, _e;};
DummyClass<QVector<int> > dummy(container);for (; dummy._b != dummy._e; ++dummy._b){...}解决了迭代器变量的问题,下面面临的是如何使用它。使用模板类,需要传入模板类型。因此,还需要能够提取模板类型。
template<typename T>T getType(const T& t) { return T(0);}使用模板推导功能来提取容器的类型,如下:
template<typename T>DummyClass<T> getNewContainer(const T& c) { return DummyClass<T>(c);}这样就可以得到一个DummyClass<Container>类型的变量。
qDebug() << *getNewContainer(container)._b;
需要有一个DummyClass<T>类型的对象,使用这个对象去操作迭代器遍历。但是这个对象的T仍然需要指明。需要一个类型A,A的对象a,可以直接取使用DummyClass<T>类型的变量。现在的问题在于如何取声明中定义这个类型A。
解决方式是使用继承,给DummyClass增加一个父类,这个父类非模板类型。
class DummyBase {};template<typename Container>class DummyClass : public DummyBase{...};这样,可以声明一个变量类型DummyBase container,然而它实际的内容是DummyClass<T>类型的派生类对象。
const DummyBase& _container = getNewContainer(container);但是实际使用的时候仍然是派生类类型,需要再增加一个转换函数:
template<typename T>const DummyClass<T>* convertDummy(const DummyBase* base, const T*) {return static_cast<const DummyClass<T>* >(base);}需要说明一下,const T*是为了推导模板使用的。
至此,模板的问题解决了。
下面就是使用for循环,DummyClass对象有了,就可以进行遍历了。
for (const DummyBase& _container = getNewContainer(container); convertDummy(&_container, &container)->_b != convertDummy(&_container, &container)->_e; ++convertDummy(&_container, &container)->_b)等等,variable还没有使用呢,该如何使用呢?
双层循环,上面的一层循环迭代器已经有了,这一层只需要将它的值赋给variable就可以了,但是还面临的是,如何结束这层的循环呢?
Qt中的做法是在DummyClass中增加一个整数标志位,上层循环的时候给一个初始值0,下层循环判断是否是1,根据它结束下层循环,并重新设置整数标志位。
下面附上完整的仿真代码:
class DummyBase {};template<class Container>class DummyClass : public DummyBase{public:typedef typename Container::const_iterator iterator;DummyClass(const Container& c) : _c(c), _b(c.begin()), _e(c.end()), _k(0) {}//iterator begin(){ return _b;}//iterator end() { return _e; }bool condition() const { return ++_k && _b != _e;}public:const Container& _c;mutable iterator _b, _e;mutable int _k;};template<class T>DummyClass<T> getNewContainer(const T& c) { return DummyClass<T>(c);}template<class T>const DummyClass<T>* convertDummy(const DummyBase* base, const T*) {return static_cast<const DummyClass<T>* >(base);}#define __Foreach(var, container) \for (const DummyBase& _container = getNewContainer(container); \convertDummy(&_container, &container)->condition(); convertDummy(&_container, &container)->_b++) \for(var = *convertDummy(&_container, &container)->_b; convertDummy(&_container, &container)->_k ; \--convertDummy(&_container, &container)->_k) \关于它的使用:QVector<int> container;container.push_back(1);container.push_back(2);container.push_back(3);container.push_back(4);__Foreach(int x, container){qDebug() << x;}关于细节实现,需要实际编码体验。
原创文章,转载请联系作者。
0 0
- Qt'中foreach的实现
- Qt中foreach的用法
- Qt中foreach的用法
- Qt中foreach的用法
- Qt中foreach的用法
- QT中foreach的使用
- Qt中foreach的用法
- QT中foreach的简单使用
- Qt中foreach及QList的使用
- Qt中foreach详解
- QT的foreach使用
- QT--foreach的用法
- GCC中实现c++的 foreach
- c++中foreach的一种实现方法
- C#中foreach的实现原理
- Java中foreach循环的实现原理
- Linq中ForEach实现
- foreach的实现原理
- C++对象数组和成员对象
- CenOS7安装Opentext Process Platform实践之平台篇
- 【 js 模块加载 】深入学习模块化加载(node.js 模块源码)
- JAR文件使用
- API.Management rest api基础知识大全电子书
- Qt'中foreach的实现
- 归一化积相关算法(NProd)原理及代码
- qq55938241此人是骗子
- 查询每个订单中订单明细中只支付了部分或为支付的订单
- poj2352 Stars(树状数组)
- 通讯协议
- iOS开发 实现指纹识别及验证
- Pascal学习之路2——输入输出
- mysql查询ID相同的某字段最大那条记录