Boost logo

Boost :

From: scleary_at_[hidden]
Date: 2000-02-24 12:26:58


john maddock wrote:
> I have a feeling that I'm going to regret bringing this up again -
but here
> goes anyway. I've been experimenting with compile time asserts and I
think
> I have an implementation that meets most of the requirements:
>
> Easy to use.
> Generates errors on the line of the assertion (for compilers tested
so
> far).
> Can be used at namespace, class, or function scope.
> Generates neither code nor data.
>
> On the down side - it uses macros, and use at namespace scope can
lead to
> unexpected name conflicts if used in multiple headers (there are
> workarounds though). I've also had problem with VC6 not recognising
> sizeof(member_variable) as a compile time constant - but that's a bug
in
> sizeof not related to the assertion code (as far as I can tell).
>
John -

Merging the line number into the name was an excellent idea! The name
conflicts can be worked around by forcing internal linkage via 'static':

#define BOOST_CT_ASSERT( B ) \
    static enum { BOOST_JOIN(_boost_assert_enum_, \
        __LINE__) = sizeof(::boost::ct_assert<(B)>) }

(or, equivalently:)

#define BOOST_CT_ASSERT( B ) \
    static const int BOOST_JOIN(_boost_assert_enum_, \
        __LINE__) = sizeof(::boost::ct_assert<(B)>)

This works through all problems I can think of:
Namespace usage:
  [3.5/3] gives us internal linkage; this combined with __LINE__ gives
us a guaranteed unique ID. However, it's deprecated (see below).
Function usage:
  [3.5] gives us no linkage.
Class usage:
  [3.5/5] gives us the same linkage as the enclosing class; however,
our name is nested, so it shouldn't conflict.
Template class usage:
  One thing we always have to be careful about is that implicit
template instantiation instantiates the declarations, but not the
definitions, of class members [14.7.1/1]. Static members, though, are
always declarations, and not definitions, even if they contain
initializers [3.1/2] [9.4.2/2]. Also, we don't need a definition (at
namespace scope) [9.4.2/4].

Note, however, that with "static" we do have some restrictions:
 . Cannot use more than one BOOST_CT_ASSERT per line
 . Cannot use within a local class [Example--
      void f() {
        struct S { BOOST_CT_ASSERT(sizeof(int) == 4); };
      } --End Example]
   (To work around, place the assertion at function scope)
 . Usage of "static" at namespace scope is deprecated [7.3.1.1/2] [D.2]

The last of these is the most serious, IMO. But it's either "use a
deprecated feature" or "cross your fingers when using in more than one
file". Besides, if it becomes common practice, it may become
"undeprecated".

This still does leave the second restriction, though. If
well-documented, I don't consider it a serious difficulty.

        -Steve


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk