C++11 Static Assertion (Static_assert)

Source: Internet
Author: User

Brief introduction

The keyword static_assert is introduced in c++0x, which is used to make assertions during compilation, so it is called a static assertion.

Its syntax is simple:static_assert(constant expression, hint-string).

If the value of the first parameter constant expression is true (true or not 0), then Static_assert does nothing, as if it does not exist, or generates a compilation error where the error is the static_assert statement, the error prompt is the second parameter prompt string.

Description

With Static_assert, we can find more errors during compilation, use a compiler to enforce some contracts, and help us improve the readability of compiled information, especially when it comes to templates.

Static_assert can be used in a global scope, in a namespace, in a class scope, in a function scope, with almost unlimited use.

When the compiler encounters a static_assert statement, it usually calculates its first argument as a constant expression immediately, but if the constant expression relies on some template arguments, then the calculation is deferred until the template is instantiated, which makes it possible to check the template parameters.

Since the concepts proposal, which was expected to join the C++0X standard, was eventually rejected, it is up to the Static_assert to check that the template parameters meet the desired task, so how to construct the appropriate constant expression, will be a topic worthy of discussion.

In terms of performance, the Static_assert does not cause any run-time performance penalty because it is an assertion during Static_assert compilation and does not generate the target code.

Example

Here's a simple example from MSDN:

Static_assert (sizeof ("64-bit code generation is not supported."); 

The static_assert is used to ensure that the compilation takes place only on a 32-bit platform and does not support a 64-bit platform, which can be placed at the beginning of the file so that it can be checked early to save compile time in case of failure.

Let's look at another example:

   struct MyClass
   2: {
   3:     char m_value;
   4:};
   
   struct Myemptyclass
   7: {
   8:     void func ();
   9:};
  
  Make sure that Myemptyclass is an empty class (there are no non-static member variables and no virtual functions)
  "Empty class needed");
  
  Make sure that MyClass is a non-empty class
  "Non-empty class needed");
  
  Template <TypeName v>
  Class MyTemplate
  19: {
  :     //Ensure that the template parameter T is a non-empty class
  £     Static_assert (
  A:         !std::is_empty<t>::value,
  At:         "T should be N non-empty class"
  :         );
  
  :     //Ensure that the template parameter U is an empty class
  :     Static_assert (
  :         Std::is_empty<u>::value,
  :         "U should is an empty class"
  :         );
  
  :     //Ensure that the template parameter v is derived directly or indirectly from the std::allocator<t>,
  Std::allocator<t>:     //or V is the
  :     Static_assert (
  :         Std::is_base_of<std::allocator<t>, V>::value,
  :         "V should inherit from Std::allocator<t>"
  Panax Notoginseng:         );
  
  39:};
  
  Only when the template is instantiated, will the three static_assert inside the MyTemplate be really calculus,
  To check if the template parameters meet expectations
  Class Mytemplate<myclass, Myemptyclass, std::allocator<myclass>>;
As we can see from this example, static_assert can be used flexibly, and we can examine a lot of things by constructing the appropriate constant expression. For example, std::is_empty and std::is_base_of are the type traits templates provided by the new standard Library of C + +, which we use to examine many types of information.

Related comparisons

We know that the existing standard for C + + has an assert, #error two facilities, is also used to check for errors, and some third-party static assertion implementations.

assert is a run-time assertion, it is used to find errors during the run, not to the compile time to find errors, nor mandatory, nor to improve the readability of the compilation information, since it is run-time check, of course, has an impact on performance, so often in the release version, The assert will be turned off;

#error can be seen as a pre-compilation assertion, not even the assertion, can only display an error message at the time of precompilation, it can do little, can participate in the pre-compilation condition check, because it can't get compile information, of course, can't do further analysis.

Then, before Stastic_assert submitted to the C++0X standard, in order to compensate for the assert and #error deficiencies, there are some third-party solutions that can be used for the compile-time static checks, such as Boost_static_assert and Loki_static_check, but since they are all using some of the compiler's cryptic features to implement the trick, portability, simplicity is not too good, but also reduce the compilation speed, And the function is not perfect, for example Boost_static_assert can not define the error message text, while Loki_static_check requires prompt text to satisfy the C + + type definition syntax.

compilation Translator Implementation

The implementation of GCC and VC is not very different, both do not support Chinese hints, very sorry, and VC only support ASCII encoding, l prefix will compile error. GCC seems to support other encodings, such as l prefixes and u prefixes, but I've tried to find the same results as ASCII encoding.

Static_assert error hint, VC is slightly friendlier than GCC, VC has a clearer description of the context and call stack, in contrast, GCC hints humble, but it is quite clear, originally, Static_ The assert is largely for the compiler to be more friendly and informative.

Applied research

Finally, for example, it is used to determine whether a class has a member of a specified name for reference and experience. In fact, Static_assert should be largely to see how to construct a constant expression, this example uses the Decltype keyword (also c++0x new features) and Sfinae skills, as well as some compiler-related techniques (mainly to solve the VC compiler Bug), Detailed technical details and principles will be explored in future articles.

   Determines whether the class contains the member variable and member function of Foo
   The implementation of GCC is basically for the implementation of standard C + +
   #ifdef __gnuc__
   
   The two overloaded versions of the Check_property_foo function, combined with decltype,
   Infer whether the specified type contains foo as a member variable by Sfinae at compile time
   Char Check_property_foo (...);
   
   Template <TypeName t>
  const& T, Decltype (& (T.foo)) p = 0);
  
  This class template shows whether T contains the member variable of Foo by Check_property_foo
  Template <TypeName t>
  Public std::integral_constant<
  :     sizeof (Check_property_foo (void*) >  
  16: {
  17:};
  
  The two overloaded versions of the Check_method_foo function, combined with decltype,
  Infer whether the specified type contains the Foo member function by Sfinae at compile time
  Char Check_method_foo (...);
  
  Template <TypeName t>
  const& T, Decltype (& (T::foo)) p = 0);
  
  This class template shows whether T contains the member function of Foo by Check_method_foo
  Template <TypeName t>
  struct Has_method_foo public  std::integral_constant<
  £ º     bool,!has_property_foo::value &&
  :     sizeof (Check_method_foo (void*) >  
  31: {
  32:};
  #endif
  
  For the implementation of the VC, because the VC compiler in the processing of Decltype and Sfinae, the existence of a bug,
  We can only use a few tricks to get around this bug.
  #ifdef _msc_ver
  
  The two overloaded versions of the Check_member_foo function, combined with decltype,
  Infer whether the specified type contains the member variable or function of Foo by Sfinae at compile time
  Char Check_member_foo (...);
  
  Template <TypeName t>
  const& T, Decltype (& (T.foo)) p = 0)->decltype (p);
  
  This class template shows whether T contains the member variable of Foo by Check_member_foo
  Template <TypeName t>
  struct Has_property_foo
  49: {
  :     bool value =
  Wuyi:         sizeof (check_member_foo (*sizeof (char) &&  
  :         std::is_pointerstatic_cast (0))) >::value;
  53:};
  54:
T: //This class template is derived by Check_member_foo whether the member function of Foo is contained
  Template <TypeName t>
  struct Has_method_foo
  58: {
  A:     bool value =
  Max:         sizeof (check_member_foo (*sizeof (char) &&  
  :         !std::is_pointerstatic_cast (0)) >::value;
  62:};
  
  #endif
  
  Define several classes for implementation detection
  struct Withpropertyfoo
  68: {
  A:     int foo;
  70:};
  
  struct Withmethodfoo
  73: {
  A:     void foo ();
  75:};
  
  struct Withrefporpertyfoo
  78: {
  :     int& foo;
  80:};
  
  struct Withoutfoo
  83: {
  :     void Bar ();
  85:};
  
  Use Static_assert to check these conditions
  "Property Foo needed");
  "Method Foo needed");
  "No property foo");
  "No methoed foo");
  "Property Foo needed");
  "No method foo");

C++11 Static Assertion (Static_assert)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.