zoukankan      html  css  js  c++  java
  • C++除法运算 // 静态断言

    1、C++中"/"运算:对两个整数做除法,结果仍为整数,如果它的商包含小数部分,则小树部分会被截除。

         C++ Primer 第五章 P130

    2、静态断言(static_assert)

    简介

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

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

    如果第一个参数常量表达式的值为真(true或者非零值),那么static_assert不做任何事情,就像它不存在一样,否则会产生一条编译错误,错误位置就是该static_assert语句所在行,错误提示就是第二个参数提示字符串。

    说明

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

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

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

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

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

     

    范例

    下面是一个来自MSDN的简单范例:

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

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

    再看另一个范例:

     1: struct MyClass
       2: {
       3:     char m_value;
       4: };
       5:  
       6: struct MyEmptyClass
       7: {
       8:     void func();
       9: };
      10:  
      11: // 确保MyEmptyClass是一个空类(没有任何非静态成员变量,也没有虚函数)
      12: static_assert(std::is_empty<MyEmptyClass>::value, "empty class needed");
      13:  
      14: //确保MyClass是一个非空类
      15: static_assert(!std::is_empty<MyClass>::value, "non-empty class needed");
      16:  
      17: template <typename T, typename U, typename V>
      18: class MyTemplate
      19: {
      20:     // 确保模板参数T是一个非空类
      21:     static_assert(
      22:         !std::is_empty<T>::value,
      23:         "T should be n non-empty class"
      24:         );
      25:  
      26:     // 确保模板参数U是一个空类
      27:     static_assert(
      28:         std::is_empty<U>::value,
      29:         "U should be an empty class"
      30:         );
      31:  
      32:     // 确保模板参数V是从std::allocator<T>直接或间接派生而来,
      33:     // 或者V就是std::allocator<T>
      34:     static_assert(
      35:         std::is_base_of<std::allocator<T>, V>::value,
      36:         "V should inherit from std::allocator<T>"
      37:         );
      38:  
      39: };
      40:  
      41: // 仅当模板实例化时,MyTemplate里面的那三个static_assert才会真正被演算,
      42: // 藉此检查模板参数是否符合期望
      43: template class MyTemplate<MyClass, MyEmptyClass, std::allocator<MyClass>>;
    通过这个例子我们可以看出来,static_assert可以很灵活的使用,通过构造适当的常量表达式,我们可以检查很多东西。比如范例中std::is_emptystd::is_base_of都是C++新的标准库提供的type traits模板,我们使用这些模板可以检查很多类型信息。

     

    相关比较

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

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

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

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

  • 相关阅读:
    欧拉回路 定理
    UESTC 1087 【二分查找】
    POJ 3159 【朴素的差分约束】
    ZOJ 1232 【灵活运用FLOYD】 【图DP】
    POJ 3013 【需要一点点思维...】【乘法分配率】
    POJ 2502 【思维是朴素的最短路 卡输入和建图】
    POJ 2240 【这题貌似可以直接FLOYD 屌丝用SPFA通过枚举找正权值环 顺便学了下map】
    POJ 1860【求解是否存在权值为正的环 屌丝做的第一道权值需要计算的题 想喊一声SPFA万岁】
    POJ 1797 【一种叫做最大生成树的很有趣的贪心】【也可以用dij的变形思想~】
    js 实现slider封装
  • 原文地址:https://www.cnblogs.com/rong86/p/3459267.html
Copyright © 2011-2022 走看看