mirror of
https://github.com/boostorg/static_assert.git
synced 2025-07-16 14:12:11 +02:00
253 lines
11 KiB
HTML
253 lines
11 KiB
HTML
![]() |
<!DOCTYPE HTML PUBLIC "-//SoftQuad Software//DTD HoTMetaL PRO 5.0::19981217::extensions to HTML 4.0//EN" "hmpro5.dtd">
|
||
|
|
||
|
<HTML>
|
||
|
|
||
|
<HEAD>
|
||
|
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
|
||
|
<META NAME="Template"
|
||
|
CONTENT="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
|
||
|
<META NAME="GENERATOR" CONTENT="Microsoft FrontPage Express 2.0">
|
||
|
<TITLE>static assertions</TITLE>
|
||
|
</HEAD>
|
||
|
|
||
|
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080">
|
||
|
<H1><IMG SRC="../../c++boost.gif" WIDTH="276" HEIGHT="86">Header <<A
|
||
|
HREF="../../boost/detail/call_traits.hpp">boost/static_assert.hpp</A>></H1>
|
||
|
<P>The header <boost/static_assert.hpp> supplies a single macro
|
||
|
BOOST_STATIC_ASSERT(x), which generates a compile time error message if the
|
||
|
integral-constant-expression <I>x</I> 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. </P>
|
||
|
<P>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: </P>
|
||
|
<PRE>Illegal use of COMPILE_TIME_ASSERTION_FAILURE<false></PRE>
|
||
|
|
||
|
<P>Which is intended to at least catch the eye!</P>
|
||
|
<P>You can use BOOST_STATIC_ASSERT at any place where you can place a
|
||
|
declaration, that is at <A HREF="#class">class</A>, <A
|
||
|
HREF="#function">function</A> or <A HREF="#namespace">namespace</A> scope, this
|
||
|
is illustrated by the following examples:</P>
|
||
|
<H3><A NAME="namespace"></A>Use at namespace scope.</H3>
|
||
|
<P>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 <B>int</B> be at least a 32-bit integral type, and that
|
||
|
<B>wchar_t</B> be an unsigned type. We can verify this at compile time as
|
||
|
follows:</P>
|
||
|
<PRE>#include <climits>
|
||
|
#include <cwchar>
|
||
|
#include <boost/static_assert.hpp>
|
||
|
|
||
|
namespace my_conditions {
|
||
|
|
||
|
BOOST_STATIC_ASSERT(sizeof(int) * CHAR_BIT >= 32);
|
||
|
BOOST_STATIC_ASSERT(WCHAR_MIN >= 0);
|
||
|
|
||
|
} // namespace my_conditions
|
||
|
</PRE>
|
||
|
|
||
|
<P>The use of the namespace <I>my_conditions</I> here requires some comment.
|
||
|
The macro BOOST_STATIC_ASSERT works by generating an <STRONG>typedef</STRONG>
|
||
|
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.</P>
|
||
|
<H3><A NAME="function"></A>Use at function scope</H3>
|
||
|
<P>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.</P>
|
||
|
<PRE>#include <iterator>
|
||
|
#include <boost/static_assert.hpp>
|
||
|
#include <boost/type_traits.hpp>
|
||
|
|
||
|
template <class RandomAccessIterator >
|
||
|
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<cat, const std::random_access_iterator_tag&>::value));
|
||
|
//
|
||
|
// detail goes here...
|
||
|
return from;
|
||
|
}</PRE>
|
||
|
|
||
|
<P>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).</P>
|
||
|
<H3><A NAME="class"></A>Use at class scope</H3>
|
||
|
<P>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:</P>
|
||
|
<PRE>#include <climits>
|
||
|
#include <boost/static_assert.hpp>
|
||
|
|
||
|
Template <class UnsignedInt>template <class UnsignedInt>
|
||
|
class myclass
|
||
|
{
|
||
|
private:
|
||
|
BOOST_STATIC_ASSERT(sizeof(UnsignedInt) * CHAR_BIT >= 16);
|
||
|
BOOST_STATIC_ASSERT(std::numeric_limits<UnsignedInt>::is_specialized
|
||
|
&& std::numeric_limits<UnsignedInt>::is_integer
|
||
|
&& !std::numeric_limits<UnsignedInt>::is_signed);
|
||
|
public:
|
||
|
/* details here */
|
||
|
};
|
||
|
</PRE>
|
||
|
|
||
|
<H3>How it works</H3>
|
||
|
<P>BOOST_STATIC_ASSERT works as follows. There is class
|
||
|
STATIC_ASSERTION_FAILURE which is defined as:</P>
|
||
|
<PRE>namespace boost{
|
||
|
|
||
|
template <bool> struct STATIC_ASSERTION_FAILURE;
|
||
|
|
||
|
template <> struct STATIC_ASSERTION_FAILURE<true>{};
|
||
|
|
||
|
}</PRE>
|
||
|
|
||
|
<P>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.</P>
|
||
|
<H3>Test Programs</H3>
|
||
|
<P>The following test programs are provided with this library:</P>
|
||
|
<TABLE BORDER="0" WIDTH="100%">
|
||
|
<TR>
|
||
|
<TD WIDTH="33%"><I>Test Program</I></TD>
|
||
|
<TD WIDTH="33%"><I>Expected to Compile</I></TD>
|
||
|
<TD WIDTH="34%"><I>Description</I></TD>
|
||
|
</TR>
|
||
|
<TR>
|
||
|
<TD WIDTH="33%"><A
|
||
|
HREF="static_assert_test.cpp">static_assert_test.cpp</A></TD>
|
||
|
<TD WIDTH="33%">Yes</TD>
|
||
|
<TD WIDTH="34%">Illustrates usage, and should always compile, really just tests
|
||
|
compiler compatibility.</TD>
|
||
|
</TR>
|
||
|
<TR>
|
||
|
<TD WIDTH="33%"><A
|
||
|
HREF="static_assert_example_1.cpp">static_assert_example_1.cpp</A></TD>
|
||
|
<TD WIDTH="33%">Platform dependent.</TD>
|
||
|
<TD WIDTH="34%">Namespace scope test program, may compile depending upon the
|
||
|
platform.</TD>
|
||
|
</TR>
|
||
|
<TR>
|
||
|
<TD WIDTH="33%"><A
|
||
|
HREF="static_assert_example_2.cpp">static_assert_example_2.cpp</A></TD>
|
||
|
<TD WIDTH="33%">Yes</TD>
|
||
|
<TD WIDTH="34%">Function scope test program.</TD>
|
||
|
</TR>
|
||
|
<TR>
|
||
|
<TD WIDTH="33%"><A
|
||
|
HREF="static_assert_example_3.cpp">static_assert_example_3.cpp</A></TD>
|
||
|
<TD WIDTH="33%">Yes</TD>
|
||
|
<TD WIDTH="34%">Class scope test program.</TD>
|
||
|
</TR>
|
||
|
<TR>
|
||
|
<TD WIDTH="33%"><A
|
||
|
HREF="static_assert_test_fail_1.cpp">static_assert_test_fail_1.cpp</A></TD>
|
||
|
<TD WIDTH="33%">No</TD>
|
||
|
<TD WIDTH="34%">Illustrates failure at namespace scope.</TD>
|
||
|
</TR>
|
||
|
<TR>
|
||
|
<TD WIDTH="33%"><A
|
||
|
HREF="static_assert_test_fail_2.cpp">static_assert_test_fail_2.cpp</A></TD>
|
||
|
<TD WIDTH="33%">No</TD>
|
||
|
<TD WIDTH="34%">Illustrates failure at non-template function scope.</TD>
|
||
|
</TR>
|
||
|
<TR>
|
||
|
<TD WIDTH="33%"><A
|
||
|
HREF="static_assert_test_fail_3.cpp">static_assert_test_fail_3.cpp</A></TD>
|
||
|
<TD WIDTH="33%">No</TD>
|
||
|
<TD WIDTH="34%">Illustrates failure at non-template class scope.</TD>
|
||
|
</TR>
|
||
|
<TR>
|
||
|
<TD WIDTH="33%"><A
|
||
|
HREF="static_assert_test_fail_4.cpp">static_assert_test_fail_4.cpp</A></TD>
|
||
|
<TD WIDTH="33%">No</TD>
|
||
|
<TD WIDTH="34%">Illustrates failure at non-template class scope.</TD>
|
||
|
</TR>
|
||
|
<TR>
|
||
|
<TD WIDTH="33%"><A
|
||
|
HREF="static_assert_test_fail_5.cpp">static_assert_test_fail_5.cpp</A></TD>
|
||
|
<TD WIDTH="33%">No</TD>
|
||
|
<TD WIDTH="34%">Illustrates failure at template class scope.</TD>
|
||
|
</TR>
|
||
|
<TR>
|
||
|
<TD WIDTH="33%"><A
|
||
|
HREF="static_assert_test_fail_6.cpp">static_assert_test_fail_6.cpp</A></TD>
|
||
|
<TD WIDTH="33%">No</TD>
|
||
|
<TD WIDTH="34%">Illustrates failure at template class member function
|
||
|
scope.</TD>
|
||
|
</TR>
|
||
|
<TR>
|
||
|
<TD WIDTH="33%"><A
|
||
|
HREF="static_assert_test_fail_7.cpp">static_assert_test_fail_7.cpp</A></TD>
|
||
|
<TD WIDTH="33%">No</TD>
|
||
|
<TD WIDTH="34%">Illustrates failure of class scope example.</TD>
|
||
|
</TR>
|
||
|
<TR>
|
||
|
<TD><A
|
||
|
HREF="static_assert_test_fail_8.cpp">static_assert_test_fail_8.cpp</A></TD>
|
||
|
<TD>No</TD>
|
||
|
<TD>Illustrates failure of function scope example.</TD>
|
||
|
</TR>
|
||
|
<TR>
|
||
|
<TD><A
|
||
|
HREF="static_assert_test_fail_9.cpp">static_assert_test_fail_9.cpp</A></TD>
|
||
|
<TD>No</TD>
|
||
|
<TD>Illustrates failure of function scope example (part 2).</TD>
|
||
|
</TR>
|
||
|
</TABLE>
|
||
|
<HR>
|
||
|
<P>Revised 27th Nov 2000</P>
|
||
|
<P>Documentation © Copyright John Maddock 2000. Permission to copy, use,
|
||
|
modify, sell and distribute this document is granted provided this copyright
|
||
|
notice appears in all copies. This document is provided "as is"
|
||
|
without express or implied warranty, and with no claim as to its suitability
|
||
|
for any purpose.</P>
|
||
|
<P>Based on contributions by Steve Cleary and John Maddock.</P>
|
||
|
<P>Maintained by <A HREF="mailto:John_Maddock@compuserve.com">John Maddock</A>,
|
||
|
the latest version of this file can be found at <A
|
||
|
HREF="http://www.boost.org/">www.boost.org</A>, and the boost discussion list
|
||
|
at <A HREF="http://www.egroups.com/list/boost">www.egroups.com/list/boost</A>.
|
||
|
</P>
|
||
|
<P> </P>
|
||
|
<P> </P>
|
||
|
</BODY>
|
||
|
</HTML>
|
||
|
|