OC 实现一个TODO宏
实现一个TODO宏
转载http://blog.sunnyxx.com/2015/03/01/todo-macro/
实现一个能产生warning的TODO宏,用于在代码里做备忘,效果:
下面一步步来实现这个宏。
Let’s do it
手动让编译器报警(报错)可以用以下几个方法:
#warning sunnyxx
#error sunnyxx
#pragma message "sunnyxx"
#pragma GCC warning "sunnyxx"
#pragma GCC error "sunnyxx"
但我们知道,带 # 的预处理指令是无法被 #define 的。好在C99提供了一个 _Pragma 运算符可以把部分 #pragma 指令字符串化:
#pragma message "sunnyxx"
// 等价于
_Pragma("message \"sunnyxx\"") // 需要注意双引号的转义
// 或
_Pragma("message(\"sunnyxx\")") // 需要注意双引号的转义
1.利用这个特性,我们就可以将warning定义成宏
#define SOME_WARNING _Pragma("message(\"报告大王!\")")
int main() {
SOME_WARNING // [!]报告大王!
return 1;
}
2.接下来,我们让这个宏能够接受入参,并显示到warning中去,这里会面临宏的基本用法的考验。
#define STRINGIFY(S) #S
#define PRAGMA_MESSAGE(MSG) _Pragma(STRINGIFY(message(MSG)))
3.个人认为不太可能在一个宏定义中完成这件事,需要用到辅助宏:STRINGIFY(S) 将入参转化成字符串,省去了_Pragma中全串加转义字符的困扰。
这时,一个基本功能的TODO宏就完成了,下面向其中加入额外的信息:
// 两个已有的宏
#define STRINGIFY(S) #S
#define PRAGMA_MESSAGE(MSG) _Pragma(STRINGIFY(message(MSG)))
// 延迟1次展开的宏
#define DEFER_STRINGIFY(S) STRINGIFY(S)
// 下面的宏在第一行用`\`折行
#define FORMATTED_MESSAGE(MSG) "[TODO-" DEFER_STRINGIFY(__COUNTER__) "] " MSG " \n" \
DEFER_STRINGIFY(__FILE__) " line " DEFER_STRINGIFY(__LINE__)
其中涉及到的知识:
- 两个常量字符串可以拼接成一个整串 “123””456” => “123456”
- 使用到3个预定义宏,__COUNTER__宏展开次数的计数器,全局唯一;__FILE__当前文件完整目录字符串;__LINE__在当前文件第几行
- 在字符串中预定义宏应延时展开,如果将上面的DEFER_STRINGIFY换成STRINGIFY的话,如__LINE__就不能被正确展开成行数,而是成了一个常量字符串"LINE"
- 为了美化,warning message中可以使用\n换行
于是,使用FORMATTED_MESSAGE(MSG)宏就可以将带文件路径、序号、行数等信息加入到最终的warning中。
4.其实到这步已经OK了,为了让这个宏更加抢眼,还可以借鉴RAC,把宏定义成前面加@的形式:
#define KEYWORDIFY try {} @catch (...) {}
5.将最终的宏定义前面加上上面的宏后,使用时就可以加@前缀了(空的try-catch会被编译器优化,所以没啥性能损耗)
最终版本
#define STRINGIFY(S) #S
#define DEFER_STRINGIFY(S) STRINGIFY(S)
#define PRAGMA_MESSAGE(MSG) _Pragma(STRINGIFY(message(MSG)))
#define FORMATTED_MESSAGE(MSG) "[TODO-" DEFER_STRINGIFY(__COUNTER__) "] " MSG " \n" \
DEFER_STRINGIFY(__FILE__) " line " DEFER_STRINGIFY(__LINE__)
#define KEYWORDIFY try {} @catch (...) {}
// 最终使用下面的宏
#define TODO(MSG) KEYWORDIFY PRAGMA_MESSAGE(FORMATTED_MESSAGE(MSG))
What’s more
Xcode插件《XTodo》也是利用这个特性,可以尝试下。
如果需要一个产生error的宏,将这里替换成这样就好了:_Pragma(STRINGIFY(GCC error(MSG)))
References
http://clang.llvm.org/docs/UsersManual.html
https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html
OC 实现一个TODO宏的更多相关文章
- 代码备忘, TODO宏实现
代码备忘, TODO宏实现 我们平时在开发过程中, 往往并非憋足气一股脑敲完所有代码.每一个模块, 每一个函数的实现总有个先后顺序. 又或者哪个部分须要做调整, 改动- 所以, 我们须要有一个东西, ...
- 用 Swift 开发一个 TODO 应用
背景 相信不少 iOS 程序员对于 Swift 依旧持以观望的态度,一来是这小家伙刚出来没几天,本身还处于完善的阶段:二来是学习的成本较高,看完官方文档怎么也要个几天的时间:三来是反正最近几年很难在工 ...
- oc是一个全动态语言,oc的一切都是基于runtime实现的!
oc是一个全动态语言,oc的一切都是基于runtime实现的! 从以下三方面来理解runtime吧! 1. 传统的面向过程的语言开发,例如c语言.实现c语言编译器很简单,只要按照语法规则实现一个LAL ...
- 用react + redux + router写一个todo
概述 最近学习redux,打算用redux + router写了一个todo.记录下来,供以后开发时参考,相信对其他人也有用. 注意: 我只实现了Footer组件的router,其它组件的实现方法是类 ...
- 用react+redux写一个todo
概述 最近学习redux,打算用redux写了一个todo.记录下来,供以后开发时参考,相信对其他人也有用. 代码 代码请见我的github 组织架构如下图:
- react写一个todo
概述 最近学习redux,打算先复习一下react,所以用react写了一个todo.记录下来,供以后开发时参考,相信对其他人也有用. 代码 代码请见我的github 组织架构如下图:
- Confluence 6 创建一个用户宏
如果你想创建自定义的宏的话,用户宏能够帮你完成这个任务.这个可以在你系统中应用特定的操作,比如说应用自定义格式等. 用户用是在 Confluence 创建和和管理的,你需要有一定的编码基础才可以. 你 ...
- Directx11教程(11) 增加一个debug宏
原文:Directx11教程(11) 增加一个debug宏 现在我们在common.h中增加一个debug的宏,在每个d3d11函数后调用,如果d3d函数出错,它能够给出程序中错误的代码行 ...
- 写一个TODO App学习Flutter本地存储工具Moor
写一个TODO App学习Flutter本地存储工具Moor Flutter的数据库存储, 官方文档: https://flutter.dev/docs/cookbook/persistence/sq ...
随机推荐
- jdbc 操作步骤
package org.db; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLExcept ...
- HDU1074 Doing Homework —— 状压DP
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1074 Doing Homework Time Limit: 2000/1000 MS (J ...
- POJ1417 True Liars —— 并查集 + DP
题目链接:http://poj.org/problem?id=1417 True Liars Time Limit: 1000MS Memory Limit: 10000K Total Submi ...
- git 一次删除所有删除的文件
/*********************************************************************************** * git 一次删除所有删除的 ...
- bzoj 1086 王室联邦 —— 思路题
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1086 一眼看去很是不会,于是看看TJ... https://blog.csdn.net/ly ...
- bzoj4806 炮——DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4806 看到这题首先会想到状压什么乱七八糟的,然而很难做: 其实,因为求的是方案数,所以并不需 ...
- Python基础第十天
一.内容
- hdu3652(含有13且能被13整除的数)数位DP基础
B-number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- Asp.net Mvc 数据库上下文初始化器
在Asp.net Mvc 和Entity FrameWork程序中,如果数据库不存在,EF默认的行为是新建一个数据库.如果模型类与已有的数据库不匹配的时候,会抛出一个异常. 通过指定数据库上下文对象初 ...
- 3198: [Sdoi2013]spring【容斥原理+hash】
容斥是ans= 至少k位置相等对数C(k,k)-至少k+1位置相等对数C(k+1,k)+至少k+2位置相等对数*C(k+2,k) -- 然后对数的话2^6枚举状态然后用hash表统计即可 至于为什么要 ...