QT_REQUIER_CONFIG
在qglobal.h中,定义了很多宏。下面这个QT_REQUIER_CONFIG,展开成:
#define QT_REQUIRE_CONFIG(feature) Q_STATIC_ASSERT_X(QT_FEATURE_##feature == 1, "Required feature " #feature " for file " __FILE__ " not available.")
注意宏定义连字符##的作用,看来Q_STATIC_ASSERT_X是一个判断句,如果feature被配置了的话,就没有问题,相反如果没有的话,就报一个错误。
就在同一个文件中,可以看到这个宏的定义:
#define Q_STATIC_ASSERT_X(Condition, Message) Q_STATIC_ASSERT(Condition)
继续寻根,还好就在同一个文件的上面一点就找到了:
#define Q_STATIC_ASSERT(Condition) \
enum {Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __COUNTER__) = sizeof(QStaticAssertFailure<!!(Condition)>)}
看到了如此复杂的宏,不觉虎躯一震。继续往上找:
#define Q_STATIC_ASSERT_PRIVATE_JOIN(A, B) Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B)
再解一次,终于到头了:
#define Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B) A ## B
其实就是将A和B连起来。
而对于赋值号后面的那个部分sizeof(QStaticAssertFailure<!!(Condition)>)},可以继续找到模板类的定义:
template <bool Test> class QStaticAssertFailure;
template <> class QStaticAssertFailure<true> {};
如果Condition存在的话,也就是被定义过的话,那么!!(Condition)就是1,对应上面的第二行,没有出现问题;否则是0,对应上面的第一行,第一行的意思是声明一个模板类,但是没有定义,所以sizeof为0。为了验证上面两句话的作用,可以新建一个工程,对这两句分别测试:
#include <QCoreApplication>
template<bool Test> class QStaticAssertFailure;
template <> class QStaticAssertFailure<true> {};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
sizeof(QStaticAssertFailure<>);
sizeof(QStaticAssertFailure<>);
return a.exec();
} template<bool Test> class QStaticAssertFailure;
- 如果,注释掉第2行和第7行,不能通过,理由是QStaticAssertFailure并非类模板;
- 当注释掉第三行时,第七第八行都会报incomplete type错误;
- 当无注释时,第7行报incomplete type错误;
- 当注释掉第7行,编译通过。
第3行的部分其实是一个explicit specialization,显式具体化。以下观点来自Typecool的博客:
具体化函数定义——显式具体化(explicit specialization)
当遇到特定类型参数,需要改变函数模板定义时,可以使用该方法。
以下实现需要 <第三代具体化(ISO/ANSI C++标准)>支持:
1、对于给定的函数名,可以有非模板函数、模板函数和显式具体化模板函数以及它们的重载版本。
2、显示具体化的原型和定义应以template<>打头,并通过名称来指出类型。
3、具体化将覆盖常规模板,而非模板函数将覆盖具体化和常规模板。(表明常规函数处于最高优先级,之后是显式具体化,最后是常规模板。)
c++的强大易用性的背后,确实有语法冗杂的问题。上面第三行template <> class QStaticAssertFailure<true> {};这里确实是一个显式具体化,它是针对于当Test是true的时候的一种具体定义。有了这个,在第八行就不会报错了
QT_REQUIER_CONFIG的更多相关文章
随机推荐
- python小技巧---打印出不同颜色的输出
在调试代码时打印常常一种颜色,找个东西真的是很难,在一次听金角大王的视频中听到了个方法,也是喀什使用了,本来不打算做记录了,可是稍微有几天不用,还得翻之前的代码,找着也是听麻烦的,现在在这里做个记录 ...
- 合并两个有序链表(java实现)
题目: 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2->4, 1->3->4 输出:1->1-&g ...
- python 【pandas】读取excel、csv数据,提高索引速度
问题描述:数据处理,尤其是遇到大量数据且需要for循环处理时,需要消耗大量时间,如代码1所示.通过data['trip_time'][i]的方式会占用大量的时间 代码1 import time t0= ...
- SWPU新闻后台登录页面
最终效果图: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <ti ...
- C语言缓冲区
定义 缓冲区是内存空间的一部分,用于缓冲输入或输出的数据.根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区. 类型 缓冲区分为三种类型:全缓冲.行缓冲和不带缓冲. 1.全缓冲 在这种情况 ...
- iOS调试踩过的坑 以及instruments使用指南
1. 低版本的XCode工程中包含的lib,在高版本的XCode中会编译错误,提示找不到库,故需要恢复libC++库到原位置上,参考 https://github.com/devdawei/libst ...
- kafka AdminClient 闲时关闭连接
AdminClient 类提供了创建.删除 topic 的 api. 在项目中创建了一个 AdminClient 对象,每次创建 topic 时,调用 org.apache.kafka.clients ...
- JVM工具jstat使用说明
输入:jstat -help得到以下帮助信息 Usage: jstat --help|-options jstat -<option> [-t] [-h<lines>] < ...
- vim 插件 -- taglist
taglist 插件是基于ctags生成的tags文件一个工具.主要是用来生成当前文件的结构.如:函数名.变量名结构.具体如下图: 下载 https://www.vim.org/scripts/scr ...
- go ethereum源码分析 PartIV Transaction相关
核心数据结构: core.types.transaction.go type Transaction struct { data txdata // caches hash atomic.Value ...