C++0x中引入了static_assert这个关键字,用来做编译期间的断言,因此叫做静态断言。

其语法:static_assert(常量表达式,提示字符串)。

如果第一个参数常量表达式的值为false,会产生一条编译错误,错误位置就是该static_assert语句所在行,第二个参数就是错误提示字符串。

使用static_assert,我们可以在编译期间发现更多的错误,用编译器来强制保证一些契约,并帮助我们改善编译信息的可读性,尤其是用于模板的时候。

static_assert可以用在全局作用域中,命名空间中,类作用域中,函数作用域中,几乎可以不受限制的使用。

编译器在遇到一个static_assert语句时,通常立刻将其第一个参数作为常量表达式进行演算,但如果该常量表达式依赖于某些模板参数,则延迟到模板实例化时再进行演算,这就让检查模板参数成为了可能。

由于之前有望加入C++0x标准的concepts提案最终被否决了,因此对于检查模板参数是否符合期望的重任,就要靠static_assert来完成了,所以如何构造适当的常量表达式,将是一个值得探讨的话题。

性能方面,由于是static_assert编译期间断言,不生成目标代码,因此static_assert不会造成任何运行期性能损失。

简单范例:

static_assert(sizeof(void *) == 4, "64-bit code generation is not supported.");

static_assert用来确保编译仅在32位的平台上进行,不支持64位的平台,该语句可以放在文件的开头处,这样可以尽早检查,以节省失败情况下的编译时间。

另一个范例:

#include <cassert>
#include <cstring>
using namespace std;template <typename T, typename U> int bit_copy(T& a, U& b){assert(sizeof(b) == sizeof(a));  //static_assert(sizeof(b) == sizeof(a), "template parameter size no equal!");memcpy(&a,&b,sizeof(b));
};int main()
{int aaa = 0x2468;double bbb;bit_copy(aaa, bbb);getchar();return 0;
}

这里使用assert运行时断言,但如果bit_copy不被调用,我们将无法触发该断言,实际上正确产生断言的时机应该在模版实例化时,即编译时期。

使用static_assert替换assert再次编译,即可获得一个错误并显示我们指定的错误信息。

注意:static_assert的断言表达式的结果必须是在编译时期可以计算的表达式,即必须是常量表达式。如果使用变量,则会导致错误。

int positive(const int n) {static_assert(n > 0, "value must > 0");return 0;
}

和Assert,#error比较

我们知道,C++现有的标准中,就有assert、#error两个设施,也是用来检查错误的,还有一些第三方的静态断言实现。

assert是运行期断言,它用来发现运行期间的错误,不能提前到编译期发现错误,也不具有强制性,也谈不上改善编译信息的可读性,既然是运行期检查,对性能当然是有影响的,所以经常在发行版本中,assert都会被关掉;

#error可看做预编译期断言,甚至都算不上断言,仅仅能在预编译时显示一个错误信息,它能做的不多,可以配合#ifdef/ifndef参与预编译的条件检查,由于它无法获得编译信息,当然就做不了更进一步分析了。

stastic_assert提交到C++0x标准之前,为了弥补assert#error的不足,出现了一些第三方解决方案,可以作编译期的静态检查,例如:BOOST_STATIC_ASSERTLOKI_STATIC_CHECK,但由于它们都是利用了一些编译器的隐晦特性实现的trick,可移植性、简便性都不是太好,还会降低编译速度,而且功能也不够完善,例如BOOST_STATIC_ASSERT就不能定义错误提示文字,而LOKI_STATIC_CHECK则要求提示文字满足C++类型定义的语法。

C++11 static_assert相关推荐

  1. 使用Clang作为编译器 —— Clang 语言扩展

    1. 介绍 本文档描述了 Clang 提供的语言扩展.除了这里列出的语言扩展之外,Clang 还旨在支持广泛的 GCC 扩展.有关这些扩展的更多信息,请参阅 GCC手册. 2. 特性检查宏 语言扩展可 ...

  2. c++11中静态断言static_assert

    c++11中的静态断言(static_assert) 在c++11中引入了,目的是在编译时就能检查处一些问题.写法如下: static_assert(常量表达式,提示字符串); 如果第一个参数常量表达 ...

  3. C++11中头文件type_traits介绍

    C++11中的头文件type_traits定义了一系列模板类,在编译期获得某一参数.某一变量.某一个类等等类型信息,主要做静态检查. 此头文件包含三部分: (1).Helper类:帮助创建编译时常量的 ...

  4. 【C++】C++11新增关键字详解

    目录 一.auto 1.auto 用来声明自动变量,表明变量存储在栈(C++11之前) 2.auto用于推断变量类型示例(C++11) 3.声明或定义函数时作为函数返回值的占位符,此时需要与关键字 d ...

  5. c++11的10个新特性

    C++11标准由国际标准化组织(ISO)和国际电工委员会(IEC)旗下的C++标准委员会(ISO/IEC JTC1/SC22/WG21)于2011年8月12日公布[2]  ,并于2011年9月出版.2 ...

  6. VS2010-2015对C++11/14/17特性的支持

    VS2010-2015对C++11/14/17特性的支持 C++11 功能列表 Visual C++ 实现了 C++11 核心语言规范 中的绝大多数功能.许多 C++14 库功能和某些为 C++17 ...

  7. C++11(及现代C++风格)和快速迭代式开发

    过去的一年我在微软亚洲研究院做输入法,我们的产品叫"英库拼音输入法" (下载Beta版),如果你用过"英库词典"(现已更名为必应词典),应该知道"英库 ...

  8. c++11 常量表达式

    c++11 常量表达式 #define _CRT_SECURE_NO_WARNINGS#include <iostream> #include <string> #includ ...

  9. Cpp / #error、static_assert、assert 区别

    一.#error 执行期间是预编译阶段,目的是配合 #ifdef / #ifndef 参与预编译的条件检查,显示一段错误信息. 二.static_assert static_assert(bool f ...

最新文章

  1. EBB-11、Linux启动流程
  2. Linux系统篇-文件系统虚拟文件系统
  3. 吸收塔如何提高吸收率_燕姐强烈推荐的一款燕窝饮,吸收率原来真的可以这么高!...
  4. linux下A免密码登录B
  5. HDU1872 稳定排序【稳定排序】
  6. 私有成员变量理解的补充
  7. mysql for macOS安装
  8. 谷歌Chrome浏览器 v0.2.149.27 Beta 提供下载
  9. Node.js 中 exports 和 module.exports 的区别
  10. iview admin 使用爬坑
  11. mysql 给已存在的商品数据,根据商品ID增加商品编号
  12. exfat最佳单元大小_回音壁构造和单元相关的个人看法
  13. 不要被后端糊弄了,我来告诉你网关是什么
  14. 实时协同编辑的实现: 编辑锁, OT算法
  15. 一个可以免费下载英文书籍的网站
  16. ITIL入门 ITSM入门 事件入门 事件管理入门
  17. 基于51单片机的LCD12864游戏机设计
  18. php网页显示中文乱码的解决办法!
  19. DevExpress 控件使用之XtraReport
  20. LAMP架构(基础篇)

热门文章

  1. 【Linux】VMware安装VMware Tools工具
  2. APACHE服务器出现No input file specified.解决方案
  3. visual studio 容器工具首次加载太慢 vsdbg\vs2017u5 exists, deleting 的解决方案
  4. EasyUI+MVC+EF简单用户管理Demo(问题及解决)
  5. Spring Boot前后端分离项目Session问题解决
  6. [Git]解决Permission denied, please try again问题
  7. 终极解决VS2015 安装失败问题,如 安装包损坏或丢失
  8. 一个如何解析XML文件? [关闭]
  9. 为什么要使用Ruby的attr_accessor,attr_reader和attr_writer?
  10. 在远程MQ上启动应用程序时,IBM MQ更改用户标识