📜  了解C++ 11中的static_assert

📅  最后修改于: 2021-05-30 11:26:44             🧑  作者: Mango

什么是静态断言?

静态断言是一种在编译代码时检查条件是否为真的方法。如果不是,则要求编译器发出错误消息并停止编译过程。需要检查的条件是一个常量表达式。

  • 执行编译时断言检查
  • 句法:
    static_assert( constant_expression, string_literal ); 

在C++ 11标准之前如何进行静态断言?

在C++ 11标准之前,产生编译时错误消息的主要方法是通过#error指令,该指令使实现产生一条诊断消息,其中包括其后的消息。例如:

// Static assertion using #error directive
#include 
using namespace std;
#if !defined(__geeksforgeeks)
#error "Geeksforgeeks hasn't been defined yet".
#endif
int main()
{
    return 0;
}

错误:尚未定义Geeksforgeeks。

#error指令有什么问题?

#error指令可以很好地完成简单的任务。但是,当需要为复杂的任务(例如,使用sizeof运算符检查数据类型的大小)进行编译时声明时,该方法将失败。这是因为诸如“ sizeof”之类的标记要等到预处理翻译阶段之后才转换为源标记,此时您不能再使用预处理指令。

从C++ 11标准开始,如何进行静态断言?

C++ 11标准引入了一个名为static_assert()的功能,该功能可用于在编译时测试软件断言。

语法

static_assert( constant_expression, string_literal );  
Parameters:
constant_expression: An integral constant expression 
that can be converted to a Boolean.
string_literal: The error message that is displayed 
when the constant_expression parameter is false. 

“ constant_expression”参数表示需要在编译期间检查的软件断言(您期望在程序的特定点上为真的条件)。如果条件为true,则static_assert声明无效。如果条件为假,则断言失败,编译器将在string_literal参数中显示消息,并且编译失败并显示错误。但是,重要的是要注意string_literal参数是可选的。

范例

// CPP code to demonstrate
// static assertion using static_assert
#include 
using namespace std;
  
template 
class Vector {
    // Compile time assertion to check if
    // the size of the vector is greater than
    // 3 or not. If any vector is declared whose
    // size is less than 4, the assertion will fail
    static_assert(Size > 3, "Vector size is too small!");
  
    T m_values[Size];
};
  
int main()
{
    Vector four; // This will work
    Vector two; // This will fail
  
    return 0;
}

输出

error: static assertion failed: Vector size is too small!

在上面的代码中,我们创建了一个名为vector的模板类,其中我们不想创建一个小于4的矢量。因此,在模板主体内,我们放置了一个static_assert语句来检查该矢量制作的尺寸> 3。如果失败,则声明将失败,并显示错误消息:“向量大小太小”。

这恰恰是在向量类对象“ two”的声明中发生的事情。传递给它的大小为“ 2”,这使要检查的条件失败,因此产生了编译时错误,从而中止了编译过程。

与#error相比,static_assert有什么优势?

  1. 与#error不同,使用static_assert的断言发生在预处理翻译阶段之后。因此,可以使用static_assert使用sizeof检查数据类型的大小。
    // Datatype
    #include 
      
    using namespace std;
    // No error produced.
    // The program compiles well because
    // the size of long datatype is 8 bytes
    static_assert(sizeof(long) == 8, 
    ode relies on 'long' being exactly 8 bytes");
    int main()
    {
        return 0;
    }
    
  2. 库可以在编译时检测常见的使用错误。
  3. C++标准库的实现可以检测和诊断常见的使用错误,从而提高可用性。

申报范围

static_assert可以在名称空间范围,类范围以及块范围中使用。每个上述范围的示例如下:

  1. 命名空间范围:
    // CPP program to illustrate
    // declaring static_assert in namespace scope
    #include 
    static_assert(sizeof(void*) == 8, 
    "DTAMDL(*LLP64) is not allowed for this module.");
    int main()
    {
        cout << "Assertion passed. 
        The program didn't produce an error";
        return 0;
    }
    

    输出

    assertion passed. The program didn't produce an error
  2. 班级范围:
    // CPP program to illustrate class scope in
    // static assertion using static_assert
    #include 
    using namespace std;
      
    template 
    class Vector {
        // Compile time assertion to check if
        // the size of the vector is greater than
        // 3 or not. If any vector is declared whose
        // size is less than 4, the assertion will fail
        static_assert(Size > 3, "Vector size is too small!");
      
        T m_values[Size];
    };
      
    int main()
    {
        Vector four; // This will work
        Vector two; // This will fail
      
        return 0;
    }
    

    输出

    error: static assertion failed: Vector size is too small!
  3. 阻止范围:
    // CPP program to illustrate
    // declaring static_assert in block scope
    template 
    void f()
    {
        static_assert(N >= 0, "length of array a is negative.");
        T a[N];
    }
    int main()
    {
        // assertion fails here
        // because the length of the array passed
        // is below 0
        f();
        return 0;
    }
    

    输出:

    error: static assertion failed: length of array a is negative.

错误的static_assert

在static_assertion中传递的constant_expression必须是有效的表达式。例如,考虑以下代码:

// CPP program to illustrate
// demonstrating an erroneous static_assert declaration
int main()
{
    static_assert(1 / 0, "never shows up!");
    return 0;
}

输出:

prog.cpp:5:2: error: non-constant condition for static assertion
  static_assert(1 / 0, "never shows up!");
  ^

在上面的代码中,表达式“ 1/0 ”不是有效的常量表达式。因此,在编译时,编译器将发出一条错误消息,指出除数不得为零,而不是在static_assert声明中显示字符串字面量。

要从最佳影片策划和实践问题去学习,检查了C++基础课程为基础,以先进的C++和C++ STL课程基础加上STL。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程”