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/example/static_assert_example_1.cpp static_assert_example_1.cpp]] [Platform dependent.] [Namespace scope test program, may compile depending upon the platform. ]] 226[[[@../../libs/static_assert/example/static_assert_example_2.cpp static_assert_example_2.cpp]] [Yes] [Function scope test program. ]] 227[[[@../../libs/static_assert/example/static_assert_example_3.cpp static_assert_example_3.cpp]] [Yes] [Class scope test program. ]] 228[[[@../../libs/static_assert/test/static_assert_test.cpp static_assert_test.cpp]] [Yes] [Illustrates usage, and should always compile, really just tests compiler compatibility.]] 229[[[@../../libs/static_assert/test/static_assert_test_fail_1.cpp static_assert_test_fail_1.cpp]] [No] [Illustrates failure at namespace scope. ]] 230[[[@../../libs/static_assert/test/static_assert_test_fail_2.cpp static_assert_test_fail_2.cpp]] [No] [Illustrates failure at non-template function scope. ]] 231[[[@../../libs/static_assert/test/static_assert_test_fail_3.cpp static_assert_test_fail_3.cpp]] [No] [Illustrates failure at non-template class scope. ]] 232[[[@../../libs/static_assert/test/static_assert_test_fail_4.cpp static_assert_test_fail_4.cpp]] [No] [Illustrates failure at non-template class scope. ]] 233[[[@../../libs/static_assert/test/static_assert_test_fail_5.cpp static_assert_test_fail_5.cpp]] [No] [Illustrates failure at template class scope. ]] 234[[[@../../libs/static_assert/test/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/test/static_assert_test_fail_7.cpp static_assert_test_fail_7.cpp]] [No] [Illustrates failure of class scope example. ]] 236[[[@../../libs/static_assert/test/static_assert_test_fail_8.cpp static_assert_test_fail_8.cpp]] [No] [Illustrates failure of function scope example. ]] 237[[[@../../libs/static_assert/test/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 244