Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/static_assert/doc/static_assert.qbk @ 33

Last change on this file since 33 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 10.2 KB
Line 
1[library Boost.StaticAssert
2    [copyright 2000 2005 Steve Cleary and John Maddock]
3    [purpose Compile time diagnostics library]
4    [license
5        Distributed under the Boost Software License, Version 1.0.
6        (See accompanying file LICENSE_1_0.txt or copy at
7        <ulink url="http://www.boost.org/LICENSE_1_0.txt">
8            http://www.boost.org/LICENSE_1_0.txt
9        </ulink>)
10    ]
11    [authors [Maddock, John], [Cleary, Steve]]
12    [category template]
13    [category testing]
14    [category generic]
15    [last-revision $Date: 2007/05/09 17:20:56 $]
16]
17
18[section:intro Overview and Tutorial]
19
20This documentation is
21[@http://boost-consulting.com/vault/index.php?action=downloadfile&filename=boost_static_assert-1.34.pdf&directory=PDF%20Documentation&
22also available in printer-friendly PDF format].
23
24The header `<boost/static_assert.hpp>` supplies a single macro `BOOST_STATIC_ASSERT(x)`,
25which generates a compile time error message if the integral-constant-expression `x`
26is not true. In other words it is the compile time equivalent of the assert macro;
27this is sometimes known as a "compile-time-assertion", but will be called a
28"static assertion" throughout these docs. Note that if the condition is `true`,
29then the macro will generate neither code nor data - and the macro can also
30be used at either namespace, class or function scope. When used in a template,
31the static assertion will be evaluated at the time the template is instantiated;
32this is particularly useful for validating template parameters.
33
34One of the aims of `BOOST_STATIC_ASSERT` is to generate readable error messages.
35These immediately tell the user that a library is being used in a manner that
36is not supported. While error messages obviously differ from compiler to compiler,
37but you should see something like:
38
39   Illegal use of STATIC_ASSERTION_FAILURE<false>
40
41Which is intended to at least catch the eye!
42
43You can use `BOOST_STATIC_ASSERT` at any place where you can place a declaration,
44that is at class, function or namespace scope, this is illustrated by the
45following examples:
46
47[section:namespace Use at namespace scope.]
48
49The macro can be used at namespace scope, if there is some requirement must
50always be true; generally this means some platform specific requirement.
51Suppose we require that `int` be at least a 32-bit integral type, and that `wchar_t`
52be an unsigned type. We can verify this at compile time as follows:
53
54   #include <climits>
55   #include <cwchar>
56   #include <limits>
57   #include <boost/static_assert.hpp>
58
59   namespace my_conditions {
60
61      BOOST_STATIC_ASSERT(std::numeric_limits<int>::digits >= 32);
62      BOOST_STATIC_ASSERT(WCHAR_MIN >= 0);
63
64   } // namespace my_conditions
65
66The use of the namespace my_conditions here requires some comment.
67The macro `BOOST_STATIC_ASSERT` works by generating an typedef declaration,
68and since the typedef must have a name, the macro generates one automatically by
69mangling a stub name with the value of `__LINE__`. When `BOOST_STATIC_ASSERT` is
70used at either class or function scope then each use of `BOOST_STATIC_ASSERT`
71is guaranteed to produce a name unique to that scope (provided you only use
72the macro once on each line). However when used in a header at namespace
73scope, that namespace can be continued over multiple headers, each of which
74may have their own static assertions, and on the "same" lines, thereby generating
75duplicate declarations. In theory the compiler should silently ignore duplicate
76typedef declarations, however many do not do so (and even if they do they are
77entitled to emit warnings in such cases). To avoid potential problems, if you
78use `BOOST_STATIC_ASSERT` in a header and at namespace scope, then enclose
79them in a namespace unique to that header.
80
81[endsect]
82
83[section:function Use at function scope]
84
85The macro is typically used at function scope inside template functions,
86when the template arguments need checking. Imagine that we have an
87iterator-based algorithm that requires random access iterators.
88If the algorithm is instantiated with iterators that do not meet our
89requirements then an error will be generated eventually, but this may
90be nested deep inside several templates, making it hard for the user to
91determine what went wrong. One option is to add a static assertion at
92the top level of the template, in that case if the condition is not met,
93then an error will be generated in a way that makes it reasonably obvious to
94the user that the template is being misused.
95
96   #include <iterator>
97   #include <boost/static_assert.hpp>
98   #include <boost/type_traits.hpp>
99
100   template <class RandomAccessIterator >
101   RandomAccessIterator foo(RandomAccessIterator from, RandomAccessIterator to)
102   {
103      // this template can only be used with
104      // random access iterators...
105      typedef typename std::iterator_traits< RandomAccessIterator >::iterator_category cat;
106      BOOST_STATIC_ASSERT((boost::is_convertible<cat, const std::random_access_iterator_tag&>::value));
107      //
108      // detail goes here...
109      return from;
110   }
111
112A couple of footnotes are in order here: the extra set of parenthesis around the
113assert, is to prevent the comma inside the `is_convertible` template being
114interpreted by the preprocessor as a macro argument separator; the target type
115for `is_convertible` is a reference type, as some compilers have problems
116using `is_convertible` when the conversion is via a user defined constructor
117(in any case there is no guarantee that the iterator tag classes are
118copy-constructible).
119
120[endsect]
121
122[section:class Use at class scope]
123
124The macro is typically used inside classes that are templates.
125Suppose we have a template-class that requires an unsigned integral type with
126at least 16-bits of precision as a template argument, we can achieve this
127using something like this:
128
129   #include <climits>
130   #include <boost/static_assert.hpp>
131
132   template <class UnsignedInt>
133   class myclass
134   {
135   private:
136      BOOST_STATIC_ASSERT((std::numeric_limits<UnsignedInt>::digits >= 16)
137                           && std::numeric_limits<UnsignedInt>::is_specialized
138                           && std::numeric_limits<UnsignedInt>::is_integer
139                           && !std::numeric_limits<UnsignedInt>::is_signed);
140   public:
141      /* details here */
142   };
143
144[endsect]
145
146[section:templates Use in templates]
147
148Normally static assertions when used inside a class or function template,
149will not be instantiated until the template in which it is used is instantiated. 
150However, there is one potential problem to watch out for: if the static assertion
151is not dependent upon one or more template parameters, then the compiler is
152permitted to evaluate the static assertion at the point it is first seen,
153irrespective of whether the template is ever instantiated, for example:
154
155   template <class T>
156   struct must_not_be_instantiated
157   {   
158      BOOST_STATIC_ASSERT(false);
159   };
160
161Will produce a compiler error with some compilers (for example Intel 8.1
162or gcc 3.4), regardless of whether the template is ever instantiated.  A
163workaround in cases like this is to force the assertion to be dependent
164upon a template parameter:
165
166   template <class T>
167   struct must_not_be_instantiated
168   {   
169      // this will be triggered if this type is instantiated
170      BOOST_STATIC_ASSERT(sizeof(T) == 0);
171   };
172
173
174[endsect]
175
176[endsect]
177
178[section:how How it works]
179
180`BOOST_STATIC_ASSERT` works as follows. There is class `STATIC_ASSERTION_FAILURE`
181 which is defined as:
182
183   namespace boost{
184
185   template <bool> struct STATIC_ASSERTION_FAILURE;
186
187   template <> struct STATIC_ASSERTION_FAILURE<true>{};
188
189   }
190
191The key feature is that the error message triggered by the undefined
192expression `sizeof(STATIC_ASSERTION_FAILURE<0>)`, tends to be consistent
193across a wide variety of compilers. The rest of the machinery of
194`BOOST_STATIC_ASSERT` is just a way to feed the `sizeof` expression into a `typedef`.
195The use of a macro here is somewhat ugly; however boost members have spent
196considerable effort trying to invent a static assert that avoided macros,
197all to no avail. The general conclusion was that the good of a static assert
198working at namespace, function, and class scope outweighed the ugliness of a macro.
199
200[endsect]
201
202[section:test Test Programs]
203
204[table Test programs provided with static_assert
205[[Test Program][Expected to Compile][Description]]
206
207[[[@../../libs/static_assert/static_assert_test.cpp static_assert_test.cpp]] [Yes] [Illustrates usage, and should always compile, really just tests compiler compatibility.]]
208[[[@../../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. ]]
209[[[@../../libs/static_assert/static_assert_example_2.cpp static_assert_example_2.cpp]] [Yes] [Function scope test program. ]]
210[[[@../../libs/static_assert/static_assert_example_3.cpp static_assert_example_3.cpp]] [Yes] [Class scope test program. ]]
211[[[@../../libs/static_assert/static_assert_test_fail_1.cpp static_assert_test_fail_1.cpp]] [No] [Illustrates failure at namespace scope. ]]
212[[[@../../libs/static_assert/static_assert_test_fail_2.cpp static_assert_test_fail_2.cpp]] [No] [Illustrates failure at non-template function scope. ]]
213[[[@../../libs/static_assert/static_assert_test_fail_3.cpp static_assert_test_fail_3.cpp]] [No] [Illustrates failure at non-template class scope. ]]
214[[[@../../libs/static_assert/static_assert_test_fail_4.cpp static_assert_test_fail_4.cpp]] [No] [Illustrates failure at non-template class scope. ]]
215[[[@../../libs/static_assert/static_assert_test_fail_5.cpp static_assert_test_fail_5.cpp]] [No] [Illustrates failure at template class scope. ]]
216[[[@../../libs/static_assert/static_assert_test_fail_6.cpp static_assert_test_fail_6.cpp]] [No] [Illustrates failure at template class member function scope. ]]
217[[[@../../libs/static_assert/static_assert_test_fail_7.cpp static_assert_test_fail_7.cpp]] [No] [Illustrates failure of class scope example. ]]
218[[[@../../libs/static_assert/static_assert_test_fail_8.cpp static_assert_test_fail_8.cpp]] [No] [Illustrates failure of function scope example. ]]
219[[[@../../libs/static_assert/static_assert_test_fail_9.cpp static_assert_test_fail_9.cpp]] [No] [Illustrates failure of function scope example (part 2). ]]
220
221]
222
223[endsect]
224
225
226
Note: See TracBrowser for help on using the repository browser.