From 81625fade872d73455ff8cc78ad6a314abdccc90 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Sat, 16 Apr 2005 16:33:02 +0000 Subject: [PATCH] Added new style docs [SVN r28280] --- doc/Jamfile.v2 | 17 ++++ doc/static_assert.qbk | 217 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 234 insertions(+) create mode 100644 doc/Jamfile.v2 create mode 100644 doc/static_assert.qbk diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 new file mode 100644 index 0000000..edc2346 --- /dev/null +++ b/doc/Jamfile.v2 @@ -0,0 +1,17 @@ + +# Copyright John Maddock 2005. Use, modification, and distribution are +# subject to the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +using quickbook ; + +xml static_assert : static_assert.qbk ; +boostbook standalone + : + static_assert + : + nav.layout=none + navig.graphics=0 + ; + + diff --git a/doc/static_assert.qbk b/doc/static_assert.qbk new file mode 100644 index 0000000..5b91da1 --- /dev/null +++ b/doc/static_assert.qbk @@ -0,0 +1,217 @@ +[library Boost.StaticAssert + [copyright 2000 2005 Steve Cleary and John Maddock] + [purpose Compile time diagnostics library] + [license + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + + http://www.boost.org/LICENSE_1_0.txt + ) + ] + [category template] + [category generic] + [category testing] + [last-revision $Date$] +] + +[section:intro Overview and Tutorial] + +The header `` 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 STATIC_ASSERTION_FAILURE + +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: + +[section:namespace 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 + #include + #include + + namespace my_conditions { + + 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. + +[endsect] + +[section:function 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 + #include + #include + + template + RandomAccessIterator foo(RandomAccessIterator from, RandomAccessIterator to) + { + // this template can only be used with + // random access iterators... + typedef typename std::iterator_traits< RandomAccessIterator >::iterator_category cat; + BOOST_STATIC_ASSERT((boost::is_convertible::value)); + // + // 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). + +[endsect] + +[section:class 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 + #include + + template + class myclass + { + private: + BOOST_STATIC_ASSERT(sizeof(UnsignedInt) * CHAR_BIT >= 16); + BOOST_STATIC_ASSERT(std::numeric_limits::is_specialized + && std::numeric_limits::is_integer + && !std::numeric_limits::is_signed); + public: + /* details here */ + }; + +[endsect] + +[section:templates Use in templates] + +Normally static assertions when used inside a class or function template, +will not be instantiated until the template in which it is used is instantiated. +However, there is one potential problem to watch out for: if the static assertion +is not dependent upon one or more template parameters, then the compiler is +permitted to evaluate the static assertion at the point it is first seen, +irrespective of whether the template is ever instantiated, for example: + + template + struct must_not_be_instantiated + { + BOOST_STATIC_ASSERT(false); + }; + +Will produce a compiler error with some compilers (for example Intel 8.1 +or gcc 3.4), regardless of whether the template is ever instantiated. A +workaround in cases like this is to force the assertion to be dependent +upon a template parameter: + + template + struct must_not_be_instantiated + { + // this will be triggered if this type is instantiated + BOOST_STATIC_ASSERT(sizeof(T) == 0); + }; + + +[endsect] + +[endsect] + +[section:how How it works] + +`BOOST_STATIC_ASSERT` works as follows. There is class `STATIC_ASSERTION_FAILURE` + which is defined as: + + namespace boost{ + + template struct STATIC_ASSERTION_FAILURE; + + template <> struct STATIC_ASSERTION_FAILURE{}; + + } + +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. + +[endsect] + +[section:test Test Programs] + +[table Test programs provided with static_assert +[[Test Program][Expected to Compile][Description]] + +[[[@../../libs/static_assert/static_assert_test.cpp static_assert_test.cpp]] [Yes] [Illustrates usage, and should always compile, really just tests compiler compatibility.]] +[[[@../../libs/static_assert/static_assert_example_1.cpp static_assert_example_1.cpp]] [Platform dependent.] [Namespace scope test program, may compile depending upon the platform. ]] +[[[@../../libs/static_assert/static_assert_example_2.cpp static_assert_example_2.cpp]] [Yes] [Function scope test program. ]] +[[[@../../libs/static_assert/static_assert_example_3.cpp static_assert_example_3.cpp]] [Yes] [Class scope test program. ]] +[[[@../../libs/static_assert/static_assert_test_fail_1.cpp static_assert_test_fail_1.cpp]] [No] [Illustrates failure at namespace scope. ]] +[[[@../../libs/static_assert/static_assert_test_fail_2.cpp static_assert_test_fail_2.cpp]] [No] [Illustrates failure at non-template function scope. ]] +[[[@../../libs/static_assert/static_assert_test_fail_3.cpp static_assert_test_fail_3.cpp]] [No] [Illustrates failure at non-template class scope. ]] +[[[@../../libs/static_assert/static_assert_test_fail_4.cpp static_assert_test_fail_4.cpp]] [No] [Illustrates failure at non-template class scope. ]] +[[[@../../libs/static_assert/static_assert_test_fail_5.cpp static_assert_test_fail_5.cpp]] [No] [Illustrates failure at template class scope. ]] +[[[@../../libs/static_assert/static_assert_test_fail_6.cpp static_assert_test_fail_6.cpp]] [No] [Illustrates failure at template class member function scope. ]] +[[[@../../libs/static_assert/static_assert_test_fail_7.cpp static_assert_test_fail_7.cpp]] [No] [Illustrates failure of class scope example. ]] +[[[@../../libs/static_assert/static_assert_test_fail_8.cpp static_assert_test_fail_8.cpp]] [No] [Illustrates failure of function scope example. ]] +[[[@../../libs/static_assert/static_assert_test_fail_9.cpp static_assert_test_fail_9.cpp]] [No] [Illustrates failure of function scope example (part 2). ]] + +] + +[endsect]