C++ Boost

postulate - Compile-Time Assertion

Introduction

detail/postulate.hpp provides a macro that can be used to test compile-time boolean conditions. This macro, BOOST_POOL_POSTULATE, takes one parameter, which is the condition to test. It will fail to compile if that condition is false. Any integral constant expression [5.19/1] may be used as the condition, which includes expressions dependent on template arguments.

BOOST_POOL_POSTULATE may be used at namespace scope, class scope, or function scope. It may not be used anywhere else; for example, inside of parameter lists. For templates, the postulate is tested when the template is instantiated. It may not be used more than once per line; multiple tests must be placed on separate lines.

If the condition is false, the compiler will trigger an error at the place where the postulate macro is used. For this reason, it is often suggested that a comment be placed on the line before the postulate to explain why it is necessary.

This file also provides a macro, BOOST_POOL_JOIN, which merges two preprocessor tokens after macro substitution. (The ## preprocessor operator merges them before macro substitution).

Examples

One of the simplest examples is to ensure that we are running on a 32-bit platform:

// This code is only valid on a 32-bit platform
BOOST_POOL_POSTULATE(sizeof(int) * CHAR_BIT == 32);

Or, for more portable code, to ensure that we are running on a 2's complement platform:

// This code must run on a 2's complement platform
BOOST_POOL_POSTULATE(~1 + 1 == -1);

More complicated usage allows arbitrary restrictions on template arguments:

template <int x, int y>
struct EmmaWoodhouse
{
  // The following tests are not actually tested until
  //  EmmaWoodhouse<X, Y> is instantiated for some X and Y

  // x has to be >= 13 because . . .
  BOOST_POOL_POSTULATE(x >= 13);

  // y has to be > x because . . .
  BOOST_POOL_POSTULATE(y > x);
  . . .
};

Symbols

Notes

No compile-time assertion mechanism is perfect. However, each one should attempt to satisfy the following requirements:

  1. Basics
    Can use compile-time constants
    It can use anything that the compiler can figure out at compile time, using the same rules as those for array sizes, not the more restrictive rules of the preprocessor.
    Stop with error
    With a false expression it will prevent the program from compiling, causing an an error.
    Portable
    It will work on any conforming compiler (uses only things in the standard).
    Practical
    It will work on currently available compilers.
    Efficient
    No real code should be generated and no storage should be used. Using it has no cost or effect on the program other than preventing it from compiling -- it doesn't change optimizations, sizes of structures, or anything like that.
  2. Error Message
    Error on correct line
    Give an error message at the line where the assertion fails. The line that the compiler reports an error on will be the line of the assertion statement.
    Good error message
    The error message will be easy to understand on any compiler.
  3. Usage
    Universal syntax
    Usable in both declarations and implementations in the same way. It can be used inside a function definition or outside a function definition, inside a class declaration or outside a class declaration.
    Simple syntax
    It can be called in a simple way, similar to assert.
    Robust syntax
    Won't silently fail on simple coding errors.
  4. Namespace pollution
    Minimal pollution
    Scopes should be polluted in a minimal way.
    Macro avoidance
    Since macros pollute every scope, they should be avoided.

The search for a good compile-time postulate has been going on for years. This solution is the result of the combined effort of at least: John Maddock, Darin Adler, Jay Zipnick, Beman Dawes, and Csaba Szepesvari. In particular, John Maddock was the person who first formulated this particular solution; whereas Csaba Szepesvari, Darin Adler, and Beman Dawes are responsible for the requirements. Jay Zipnick is responsible for the name "postualte."

Dependencies

None.

Selected Quotations from the Standard

5.19/1: Expressions: Constant Expressions: ". . . An integral constant expression can involve only literals (2.13), enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions (8.5), non-type template parameters of integral or enumeration types, and sizeof expressions. Floating literals (2.13.3) can appear only if they are cast to integral or enumeration types. Only type conversions to integral or enumeration types can be used. In particular, except in sizeof expressions, functions, class objects, pointers, or references shall not be used, and assignment, increment, decrement, function-call, or comma operators shall not be used."

Future Directions

This header will soon be replaced by the Boost static assert library.


Copyright © 2000, 2001 Stephen Cleary (shammah@voyager.net)

This file can be redistributed and/or modified under the terms found in copyright.html

This software and its documentation is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.