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