Boost logo

Boost :

From: Greg Chicares (chicares_at_[hidden])
Date: 2001-05-24 22:49:04


Beman Dawes wrote:
>
> This program works as expected with the GNU, Metrowerks, and Microsoft
> compilers:
>
> #include <iostream>
> #include <boost/static_assert.hpp>
>
> template< typename T >
> void f( T & t )
> {
> std::cout << sizeof(T) << "\n";
> BOOST_STATIC_ASSERT( sizeof(T) ); // line in question
> }
>
> int main()
> {
> long l;
> f(l);
> return 0;
> }
>
> With the Borland 5.5.1 and Intel 5.0 compilers, the BOOST_STATIC_ASSERT
> fails:
>
> Borland:
> Error E2450 c:/boost/site/libs/smart_ptr/test.cpp 8: Undefined structure
> 'boost:
> :STATIC_ASSERTION_FAILURE<4>' in function f<long>(long &)
> Error E2109 c:/boost/site/libs/smart_ptr/test.cpp 8: Not an allowed type in
> func
> tion f<long>(long &)
>
> Intel:
> c:/boost/site/libs/smart_ptr/test.cpp(8) : error #70: incomplete type is
> not allowed
> BOOST_STATIC_ASSERT( sizeof(T) );
> ^
> detected during instantiation of "void f(T &) [with T=long]"

I don't know about intel, but it looks like borland doesn't convert
an integral-type value that's neither 0 nor 1 to bool(true) here

  template <bool> struct STATIC_ASSERTION_FAILURE;

while gcc does.

Simplified example:

   BOOST_STATIC_ASSERT( 1 ); // OK
   BOOST_STATIC_ASSERT( 4 ); // asserts (with borland)

If the purpose of the macro is only to verify that something which
is notionally bool is not false, then is there any harm in saying
that a bit more explicitly?

- BOOST_STATIC_ASSERT( sizeof(T) ); // line in question
+ BOOST_STATIC_ASSERT( !!sizeof(T) );

This works with borland 5.5.1 . I don't like '!!' in general
because it masks problems with uninitialized bools, but the
domain of BOOST_STATIC_ASSERT is integral-constant-expressions,
so it seems OK here.

Assuming it's desired that
   BOOST_STATIC_ASSERT( 4 );
not assert (for compatibility with the standard assert macro),
would this be an appropriate change to static_assert.hpp?

  // alternative enum based implementation:
  #define BOOST_STATIC_ASSERT( B ) \
     enum { BOOST_ASSERT_JOIN(boost_static_assert_enum_, __LINE__) \
- = sizeof(::boost::STATIC_ASSERTION_FAILURE< ( B ) >) }
+ = sizeof(::boost::STATIC_ASSERTION_FAILURE< ( !!B ) >) }
  #endif

(At least at the present time, the alternative enum implementation
is used only for borland; maybe something similar should be done
for intel too?)

/boost/boost_1_21_2/libs/static_assert/static_assert.htm says:

  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 x is not true.
                                               [^^^^^^^^^^^]
  In other words it is the compile time equivalent of the
  assert macro

Should 'is not true' be changed? E.g.
  if the integral-constant-expression x, when converted to bool,
  is not true. ^^^^^^^^^^^^^^^^^^^^^^^^^

> Are these compilers wrong, or is there a problem with BOOST_STATIC_ASSERT?
>
> (Both produce the expected output if the line in question is commented
> out.)

I think it's equivalent to this simplified test case:

template <bool> struct X;

template <> struct X<true>{};

int main()
{
   sizeof( X<4> ); // gcc: OK; borland: not OK
}

Isn't it an error not to accept the conversion 4 --> true [conv.bool]?


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