• 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++类型定义的语法。

  • 相关阅读:
    第一节:从程序集的角度分析System.Web.Caching.Cache ,并完成基本封装。
    大话缓存
    第二节:SQLServer的安装及使用
    OpenCV特征点检测——ORB特征
    Opencv学习笔记--Harris角点检测
    关于Yuri Boykov and Vladimir Kolmogorov 于2004年提出的max flow / min cut的算法的详解
    [论文笔记] CUDA Cuts: Fast Graph Cuts on the GPU
    Graph Cut and Its Application in Computer Vision
    OpenCV中openMP的使用
    四种简单的图像显著性区域特征提取方法-----> AC/HC/LC/FT。
  • 原文地址:https://www.cnblogs.com/rong86/p/3459267.html
Copyright © 2020-2023  润新知