diff --git a/static_assert.htm b/static_assert.htm index 0f6061e..a50d49e 100644 --- a/static_assert.htm +++ b/static_assert.htm @@ -1,45 +1,58 @@ - - - - - - - - -static assertions - + - -

Header <boost/static_assert.hpp>

-

The header <boost/static_assert.hpp> supplies a single macro -BOOST_STATIC_ASSERT(x), which generates a compile time error message if the -integral-constant-expression x is not true. In other words it is the -compile time equivalent of the assert macro; this is sometimes known as a + + + + +static assertions + + + + +

Header +<boost/static_assert.hpp>

+ +

The header <boost/static_assert.hpp> supplies a single +macro BOOST_STATIC_ASSERT(x), which generates a compile time +error message if the integral-constant-expression +x is not true. In other words it is the compile time +equivalent of the assert macro; this is sometimes known as a "compile-time-assertion", but will be called a "static -assertion" throughout these docs. Note that if the condition is true, then -the macro will generate neither code nor data - and the macro can also be used -at either namespace, class or function scope. When used in a template, the -static assertion will be evaluated at the time the template is instantiated; -this is particularly useful for validating template parameters.

-

One of the aims of BOOST_STATIC_ASSERT is to generate readable error -messages. These immediately tell the user that a library is being used in a -manner that is not supported. While error messages obviously differ from -compiler to compiler, but you should see something like:

-
Illegal use of COMPILE_TIME_ASSERTION_FAILURE<false>
+assertion" throughout these docs. Note that if the condition +is true, then the macro will generate neither code nor data - and +the macro can also be used at either namespace, class or function +scope. When used in a template, the static assertion will be +evaluated at the time the template is instantiated; this is +particularly useful for validating template parameters.

-

Which is intended to at least catch the eye!

-

You can use BOOST_STATIC_ASSERT at any place where you can place a -declaration, that is at class, function or namespace scope, this -is illustrated by the following examples:

-

Use at namespace scope.

-

The macro can be used at namespace scope, if there is some requirement must -always be true; generally this means some platform specific requirement. -Suppose we require that int be at least a 32-bit integral type, and that -wchar_t be an unsigned type. We can verify this at compile time as -follows:

-
#include <climits>
+

One of the aims of BOOST_STATIC_ASSERT is to generate readable +error messages. These immediately tell the user that a library is +being used in a manner that is not supported. While error +messages obviously differ from compiler to compiler, but you +should see something like:

+ +
Illegal use of COMPILE_TIME_ASSERTION_FAILURE<false>
+ +

Which is intended to at least catch the eye!

+ +

You can use BOOST_STATIC_ASSERT at any place where you can +place a declaration, that is at class, function or namespace +scope, this is illustrated by the following examples:

+ +

Use at namespace scope.

+ +

The macro can be used at namespace scope, if there is some +requirement must always be true; generally this means some +platform specific requirement. Suppose we require that int +be at least a 32-bit integral type, and that wchar_t be an +unsigned type. We can verify this at compile time as follows:

+ +
#include <climits>
 #include <cwchar>
 #include <boost/static_assert.hpp>
 
@@ -49,35 +62,41 @@ BOOST_STATIC_ASSERT(sizeof(int) * CHAR_BIT >= 32);
 BOOST_STATIC_ASSERT(WCHAR_MIN >= 0);
 
 } // namespace my_conditions
-
+
-

The use of the namespace my_conditions here requires some comment. -The macro BOOST_STATIC_ASSERT works by generating an typedef -declaration, and since the typedef must have a name, the macro generates one -automatically by mangling a stub name with the value of __LINE__. When -BOOST_STATIC_ASSERT is used at either class or function scope then each use of -BOOST_STATIC_ASSERT is guaranteed to produce a name unique to that scope -(provided you only use the macro once on each line). However when used in a -header at namespace scope, that namespace can be continued over multiple -headers, each of which may have their own static assertions, and on the -"same" lines, thereby generating duplicate declarations. In theory -the compiler should silently ignore duplicate typedef declarations, however -many do not do so (and even if they do they are entitled to emit warnings in -such cases). To avoid potential problems, if you use BOOST_STATIC_ASSERT in a -header and at namespace scope, then enclose them in a namespace unique to that -header.

-

Use at function scope

-

The macro is typically used at function scope inside template functions, -when the template arguments need checking. Imagine that we have an -iterator-based algorithm that requires random access iterators. If the -algorithm is instantiated with iterators that do not meet our requirements then -an error will be generated eventually, but this may be nested deep inside -several templates, making it hard for the user to determine what went wrong. -One option is to add a static assertion at the top level of the template, in -that case if the condition is not met, then an error will be generated in a way -that makes it reasonably obvious to the user that the template is being -misused.

-
#include <iterator>
+

The use of the namespace my_conditions here requires +some comment. The macro BOOST_STATIC_ASSERT works by generating +an typedef declaration, and since the typedef +must have a name, the macro generates one automatically by +mangling a stub name with the value of __LINE__. When +BOOST_STATIC_ASSERT is used at either class or function scope +then each use of BOOST_STATIC_ASSERT is guaranteed to produce a +name unique to that scope (provided you only use the macro once +on each line). However when used in a header at namespace scope, +that namespace can be continued over multiple headers, each of +which may have their own static assertions, and on the "same" +lines, thereby generating duplicate declarations. In theory the +compiler should silently ignore duplicate typedef declarations, +however many do not do so (and even if they do they are entitled +to emit warnings in such cases). To avoid potential problems, if +you use BOOST_STATIC_ASSERT in a header and at namespace scope, +then enclose them in a namespace unique to that header.

+ +

Use at function scope

+ +

The macro is typically used at function scope inside template +functions, when the template arguments need checking. Imagine +that we have an iterator-based algorithm that requires random +access iterators. If the algorithm is instantiated with iterators +that do not meet our requirements then an error will be generated +eventually, but this may be nested deep inside several templates, +making it hard for the user to determine what went wrong. One +option is to add a static assertion at the top level of the +template, in that case if the condition is not met, then an error +will be generated in a way that makes it reasonably obvious to +the user that the template is being misused.

+ +
#include <iterator>
 #include <boost/static_assert.hpp>
 #include <boost/type_traits.hpp>
 
@@ -91,21 +110,25 @@ RandomAccessIterator foo(RandomAccessIterator from, RandomAccessIterator to)
    //
    // detail goes here...
    return from;
-}
+}
-

A couple of footnotes are in order here: the extra set of parenthesis around -the assert, is to prevent the comma inside the is_convertible template being -interpreted by the preprocessor as a macro argument separator; the target type -for is_convertible is a reference type, as some compilers have problems using -is_convertible when the conversion is via a user defined constructor (in any -case there is no guarantee that the iterator tag classes are -copy-constructible).

-

Use at class scope

-

The macro is typically used inside classes that are templates. Suppose we -have a template-class that requires an unsigned integral type with at least -16-bits of precision as a template argument, we can achieve this using -something like this:

-
#include <climits>
+

A couple of footnotes are in order here: the extra set of +parenthesis around the assert, is to prevent the comma inside the +is_convertible template being interpreted by the preprocessor as +a macro argument separator; the target type for is_convertible is +a reference type, as some compilers have problems using +is_convertible when the conversion is via a user defined +constructor (in any case there is no guarantee that the iterator +tag classes are copy-constructible).

+ +

Use at class scope

+ +

The macro is typically used inside classes that are templates. +Suppose we have a template-class that requires an unsigned +integral type with at least 16-bits of precision as a template +argument, we can achieve this using something like this:

+ +
#include <climits>
 #include <boost/static_assert.hpp>
 
 Template <class UnsignedInt>template <class UnsignedInt>
@@ -119,133 +142,137 @@ private:
 public:
    /* details here */
 };
-
+
-

How it works

-

BOOST_STATIC_ASSERT works as follows. There is class -STATIC_ASSERTION_FAILURE which is defined as:

-
namespace boost{
+

How it works

+ +

BOOST_STATIC_ASSERT works as follows. There is class +STATIC_ASSERTION_FAILURE which is defined as:

+ +
namespace boost{
 
 template <bool> struct STATIC_ASSERTION_FAILURE;
 
 template <> struct STATIC_ASSERTION_FAILURE<true>{};
 
-}
+}
-

The key feature is that the error message triggered by the undefined -expression sizeof(STATIC_ASSERTION_FAILURE<0>), tends to be consistent -across a wide variety of compilers. The rest of the machinery of -BOOST_STATIC_ASSERT is just a way to feed the sizeof expression into a typedef. -The use of a macro here is somewhat ugly; however boost members have spent -considerable effort trying to invent a static assert that avoided macros, all -to no avail. The general conclusion was that the good of a static assert -working at namespace, function, and class scope outweighed the ugliness of a -macro.

-

Test Programs

-

The following test programs are provided with this library:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Test ProgramExpected to CompileDescription
static_assert_test.cppYesIllustrates usage, and should always compile, really just tests -compiler compatibility.
static_assert_example_1.cppPlatform dependent.Namespace scope test program, may compile depending upon the -platform.
static_assert_example_2.cppYesFunction scope test program.
static_assert_example_3.cppYesClass scope test program.
static_assert_test_fail_1.cppNoIllustrates failure at namespace scope.
static_assert_test_fail_2.cppNoIllustrates failure at non-template function scope.
static_assert_test_fail_3.cppNoIllustrates failure at non-template class scope.
static_assert_test_fail_4.cppNoIllustrates failure at non-template class scope.
static_assert_test_fail_5.cppNoIllustrates failure at template class scope.
static_assert_test_fail_6.cppNoIllustrates failure at template class member function -scope.
static_assert_test_fail_7.cppNoIllustrates failure of class scope example.
static_assert_test_fail_8.cppNoIllustrates failure of function scope example.
static_assert_test_fail_9.cppNoIllustrates failure of function scope example (part 2).
-
-

Revised 27th Nov 2000

-

Documentation © Copyright John Maddock 2000. Permission to copy, use, -modify, sell and distribute this document is granted provided this copyright -notice appears in all copies. This document is provided "as is" -without express or implied warranty, and with no claim as to its suitability -for any purpose.

-

Based on contributions by Steve Cleary and John Maddock.

-

Maintained by John Maddock, -the latest version of this file can be found at www.boost.org, and the boost discussion list -at www.egroups.com/list/boost. -

-

 

-

 

- - +

The key feature is that the error message triggered by the +undefined expression sizeof(STATIC_ASSERTION_FAILURE<0>), +tends to be consistent across a wide variety of compilers. The +rest of the machinery of BOOST_STATIC_ASSERT is just a way to +feed the sizeof expression into a typedef. The use of a macro +here is somewhat ugly; however boost members have spent +considerable effort trying to invent a static assert that avoided +macros, all to no avail. The general conclusion was that the good +of a static assert working at namespace, function, and class +scope outweighed the ugliness of a macro.

+

Test Programs

+ +

The following test programs are provided with this library:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test ProgramExpected to CompileDescription
static_assert_test.cppYesIllustrates usage, and should always + compile, really just tests compiler compatibility.
static_assert_example_1.cppPlatform dependent.Namespace scope test program, may compile + depending upon the platform.
static_assert_example_2.cppYesFunction scope test program.
static_assert_example_3.cppYesClass scope test program.
static_assert_test_fail_1.cppNoIllustrates failure at namespace scope.
static_assert_test_fail_2.cppNoIllustrates failure at non-template + function scope.
static_assert_test_fail_3.cppNoIllustrates failure at non-template class + scope.
static_assert_test_fail_4.cppNoIllustrates failure at non-template class + scope.
static_assert_test_fail_5.cppNoIllustrates failure at template class + scope.
static_assert_test_fail_6.cppNoIllustrates failure at template class + member function scope.
static_assert_test_fail_7.cppNoIllustrates failure of class scope + example.
static_assert_test_fail_8.cppNoIllustrates failure of function scope example.
static_assert_test_fail_9.cppNoIllustrates failure of function scope example (part 2).
+ +
+ +

Revised 27th Nov 2000

+ +

Documentation © Copyright John Maddock 2000. Permission to +copy, use, modify, sell and distribute this document is granted +provided this copyright notice appears in all copies. This +document is provided "as is" without express or implied +warranty, and with no claim as to its suitability for any purpose.

+ +

Based on contributions by Steve Cleary and John Maddock.

+ +

Maintained by John +Maddock, the latest version of this file can be found at www.boost.org, and the boost +discussion list at www.egroups.com/list/boost. +

+ +

 

+ +

 

+ +