tbox中tb_for的使用

在接触tbox这个开源库的时候,见识到了一个非常神奇的宏用来实现C语言的for-each循环,不禁让我很佩服作者的设计思路,想拿出来分享一下。

// 输入一共五个参数,type为元素类型,item为遍历取出的元素,head为容器的索引头,tail为容器的索引尾,iterator为自定义的迭代器
#define tb_for(type, item, head, tail, iterator) \
            /* iterator */ \
            // 先是用断言检查迭代器异常
            tb_iterator_ref_t item##_iterator = (tb_iterator_ref_t)iterator; \
            tb_assert(!item##_iterator || (tb_iterator_mode(item##_iterator) & (TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_RACCESS))); \
            /* init */ \
            // 这里进行初始化操作
            type item; \
            tb_size_t item##_itor = head; \
            tb_size_t item##_head = head; \
            tb_size_t item##_tail = tail; \
            /* walk */ \
            // 开始遍历前先确认容器是否可以遍历,可以的话进入for循环
            if (item##_iterator && item##_head != item##_tail) \
                for (   ; \
                        // 如果没到最后一个元素则返回真继续遍历并且赋值给item贡开发者使用
                        // 为了防止这个元素值为0后面又加了个1保证&&后面的条件一定为真
                        item##_itor != item##_tail && ((item = (type)tb_iterator_item(item##_iterator, item##_itor)), 1); \
                        // 迭代器指向下一个元素
                        item##_itor = tb_iterator_next(item##_iterator, item##_itor))

上面的宏需要指定头部索引与尾部索引,那么可以简化一下写成如下形式只需提供迭代器即可遍历:

#define tb_for_all(type, item, iterator) \
            tb_iterator_ref_t item##_iterator_all = (tb_iterator_ref_t)iterator; \
            tb_for(type, item, tb_iterator_head(item##_iterator_all), tb_iterator_tail(item##_iterator_all), item##_iterator_all)

具体使用的时候,以tbox的hashmap为例:

tb_for_all(tb_hash_map_item_ref_t, item, iterator)
{
     if (item) tb_trace_d("item: %p => %p", item->name, item->data);
}

大括号中拿到的item就是hashmap中的键值对,使用起来就像内置的关键字一样方便。
进一步扩展还可以增加一个条件判断:

#define tb_for_if(type, item, head, tail, iterator, cond) \
            /* iterator */ \
            tb_iterator_ref_t item##_iterator = (tb_iterator_ref_t)iterator; \
            tb_assert(!item##_iterator || (tb_iterator_mode(item##_iterator) & (TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_RACCESS))); \
            /* init */ \
            type item; \
            tb_size_t item##_itor = head; \
            tb_size_t item##_head = head; \
            tb_size_t item##_tail = tail; \
            /* walk */ \
            if (item##_iterator && item##_head != item##_tail) \
                for (   ; \
                        item##_itor != item##_tail && ((item = (type)tb_iterator_item(item##_iterator, item##_itor)), 1); \
                        item##_itor = tb_iterator_next(item##_iterator, item##_itor)) if ((cond))

tbox的github链接如下:
https://github.com/tboox/tbox

你可能感兴趣的:(tbox中tb_for的使用)