BOOST_STATIC_ASSERT


Header: "boost/static_assert.hpp"

Performing assertions at runtime is something that you probably do regularly, and for good reasons. It is an excellent way of testing preconditions, postconditions, and invariants. There are many variations for performing runtime assertions, but how do you assert at compile time? Of course, the only way to do that is to have the compiler generate an error, and while that is quite trivial (I've inadvertently done it many thousand times), it's not obvious how to get meaningful information into the error message. Furthermore, even if you find a way on one compiler, it's a lot harder to do it portably. This is the rationale for BOOST_STATIC_ASSERT. It can be used at different scopes, as we shall see.

Usage

To start using static assertions, include the header "boost/static_assert.hpp". This header defines the macro[2] BOOST_STATIC_ASSERT. For the first demonstration of its usage, we'll see how it is used at class scope. Consider a parameterized class that requires that the types with which it is instantiated are of integral type. We'd rather not provide specializations for all of those types, so what we need is to assert, at compile time, that whatever type our class is being parameterized on is indeed an integral type. Now, we're going to get a little bit ahead of ourselves by using another Boost library for testing the typeBoost.Type_traits. We'll use a predicate called is_integral, which performs a compile time evaluation of its argument and, as you might guess from its name, indicates whether that type is an integral type.

[2] Yes, it's a macro. They too can be useful, you know.

 #include <iostream> #include "boost/type_traits.hpp" #include "boost/static_assert.hpp" template <typename T> class only_compatible_with_integral_types {   BOOST_STATIC_ASSERT(boost::is_integral<T>::value); }; 

With this assertion, trying to instantiate the class only_compatible_with_integral_types with a type that is not an integral type causes a failure at compile time. The output depends on the compiler, but it is surprisingly consistent on most compilers.

Suppose we tried to instantiate the class like this:

 only_compatible_with_integral_types<double> test2; 

The compiler output will look something like this:

 Error: use of undefined type   'boost::STATIC_ASSERTION_FAILURE<false>' 

At class scope, you can ensure certain requirements for the class: For a template like this, the parameterizing type is an obvious example. You could also use assertions for other assumptions that the class makes, such as the size of certain types and such.

BOOST_STATIC_ASSERT at Function Scope

BOOST_STATIC_ASSERT can also be used at function scope. For example, consider a function that is parameterized on a non-type template parameterlet's assume an intand the parameter can accept values between 1 and 10. Rather than asserting that this precondition holds at runtime, we can enforce it at compile time using a static assertion.

 template <int i> void accepts_values_between_1_and_10() {   BOOST_STATIC_ASSERT(i>=1 && i<=10); } 

Users of this function can never instantiate it with values outside of the permitted range. The requirement on the expression in the assertion is, of course, that it be purely a compile time expressionthat is, the arguments and operators in the expression must all be known to the compiler. BOOST_STATIC_ASSERT is not, by any means, confined to use in parameterized functions; we can just as easily test requirements in any function. For example, if a function makes platform dependent assumptions, asserting that these hold is often necessary.

 void expects_ints_to_be_4_bytes() {   BOOST_STATIC_ASSERT(sizeof(int)==4); } 

Summary

Static assertions like the ones you've seen here are becoming as common in C++ as their runtime companion assert. This is, at least in part, due to the "metaprogramming revolution," where much of a program's computation is performed at compile time. The only way to express compile time assertions is by having the compiler issue an error. To make the assertions usable, the error messages must convey the necessary information, but that's hard to do portably (in fact, it's hard to do at all). This is what BOOST_STATIC_ASSERT does, by providing consistent output for compile time assertions on a wide range of compilers. It can be used at namespace, class, and function, scope.

Use BOOST_STATIC_ASSERT when:

  • A condition can be expressed at compile time

  • Requirements on types are expressible at compile time

  • You need to assert a relation of two or more constant integral values



    Beyond the C++ Standard Library(c) An Introduction to Boost
    Beyond the C++ Standard Library: An Introduction to Boost
    ISBN: 0321133544
    EAN: 2147483647
    Year: 2006
    Pages: 125

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net